Язык программирования C#9 и платформа .NET5
1 < 102 < 103 < 108 < 104 < 101 < 102 < 103 < 108 < 10Среда Visual Studio обладает одной полезной особенностью: если вы поместите точку останова перед оценкой запроса LINQ, то получите возможность просматривать содержимое во время сеанса отладки. Просто наведите курсор мыши на переменную результирующего набора LINQ (
на рис. 13.1) и вам будет предложено выполнить запрос, развернув узел Results View (Представление результатов).subsetРоль немедленного выполнения
Когда требуется оценить выражение LINQ, выдающее последовательность, за пределами логики
, можно вызывать любое количество расширяющих методов, определенных в типеforeach, таких какEnumerable,ТоArray<Т>()иToDictionary<TSource, ТКеу>(). Все методы приводят к выполнению запроса LINQ в момент их вызова для получения снимка данных. Затем полученным снимком данных можно манипулировать независимым образом.ToList<T>()Кроме того, запрос выполняется немедленно в случае поиска только одного элемента. Метод
возвращает первый элемент последовательности (и должен всегда применяться с конструкциейFirst()). Методorderbyвозвращает стандартное значение для типа элемента в последовательности, если возвращать нечего, например, когда исходная последовательность пуста или конструкцияFirstOrDefault()отбросила все элементы. Методwhereтакже возвращает первый элемент последовательности (на основеSingle()или согласно порядку следования элементов, если конструкцияorderbyотсутствует). Подобно аналогично именованному эквиваленту методorderbyвозвращает стандартное значение для типа элемента в последовательности, если последовательность пуста (или конструкцияSingleOrDefault()отбросила все элементы). Отличие между методамиwhereиFirst(OrDefault)заключается в том, чтоSingle(OrDefault)сгенерирует исключение, если из запроса будет возвращено более одного элемента.Single(OrDefault)static void ImmediateExecution(){Console.WriteLine();Console.WriteLine("Immediate Execution");int[] numbers = { 10, 20, 30, 40, 1, 2, 3, 8 };// Получить первый элемент в порядке последовательностиint number = (from i in numbers select i).First();Console.WriteLine("First is {0}", number);// Получить первый элемент в порядке запросаnumber = (from i in numbers orderby i select i).First();Console.WriteLine("First is {0}", number);// Получить один элемент, который соответствует запросуnumber = (from i in numbers where i > 30 select i).Single();Console.WriteLine("Single is {0}", number);try{// В случае возвращения более одного элемента генерируется исключениеnumber = (from i in numbers where i > 10 select i).Single();}catch (Exception ex){Console.WriteLine("An exception occurred: {0}", ex.Message);}<b> // Получить данные НЕМЕДЛЕННО как int[].</b>int[] subsetAsIntArray =(from i in numbers where i < 10 select i).ToArray<int>();<b> // Получить данные НЕМЕДЛЕННО как List<int>.</b>List<int> subsetAsListOfInts =(from i in numbers where i < 10 select i).ToList<int>();}Обратите внимание, что для вызова методов
выражение LINQ целиком помещено в круглые скобки с целью приведения к корректному внутреннему типу (каким бы он ни был).EnumerableВспомните из главы 10, что если компилятор C# в состоянии однозначно определить параметр типа обобщенного элемента, то вы не обязаны указывать этот параметр типа. Следовательно,
(илиТоArray<Т>()) можно было бы вызвать так:ToList<T>()int[] subsetAsIntArray =(from i in numbers where i < 10 select i).ToArray();Полезность немедленного выполнения очевидна, когда нужно возвратить результаты запроса LINQ внешнему вызывающему коду, что и будет темой следующего раздела главы.
Возвращение результатов запроса LINQ
Внутри класса (или структуры) можно определить поле, значением которого будет результат запроса LINQ. Однако для этого нельзя использовать неявную типизацию (т.к. ключевое слово
не может применяться к полям), и целью запроса LINQ не могут быть данные уровня экземпляра, а потому он должен быть статическим. С учетом указанных ограничений необходимость в написании кода следующего вида будет возникать редко:var
