KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Базы данных » Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю

Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Троелсен Эндрю, "Язык программирования C#9 и платформа .NET5" бесплатно, без регистрации.
Перейти на страницу:

System.Collections.IEnumerable subset =

  from i in numbers

  where i < 10

  select i;

К счастью, неявная типизация при работе с запросами LINQ значительно проясняет картину:

static void QueryOverInts()

{

  int[] numbers = {10, 20, 30, 40, 1, 2, 3, 8};

<b>  // Здесь используется неявная типизация...</b>

  var subset = from i in numbers where i &lt; 10 select i;

<b>  // ...и здесь тоже.</b>

  foreach (var i in subset)

  {

    Console.WriteLine(&quot;Item: {0} &quot;, i);

  }

  ReflectOverQueryResults(subset);

}

В качестве эмпирического правила: при захвате результатов запроса LINQ всегда необходимо использовать неявную типизацию. Однако помните, что (в большинстве случаев) действительное возвращаемое значение имеет тип, реализующий интерфейс

IEnumerable&lt;T&gt;
.

Какой точно тип кроется за ним (

OrderedEnumerable&lt;TElement, ТКеу&gt;
,
WhereArrayIterator&lt;T&gt;
и т.п.), к делу не относится, и определять его вовсе не обязательно. Как было показано в предыдущем примере кода, для прохода по извлеченным данным можно просто применить ключевое слово var внутри конструкции
foreach
.

LINQ и расширяющие методы

Несмотря на то что в текущем примере совершенно не требуется напрямую писать какие-то расширяющие методы, на самом деле они благополучно используются на заднем плане. Выражения запросов LINQ могут применяться для прохода по содержимому контейнеров данных, которые реализуют обобщенный интерфейс

IEnumerable&lt;T&gt;
. Тем не менее, класс
System.Array
(используемый для представления массива строк и массива целых чисел) не реализует этот контракт:

// Похоже, что тип System.Array не реализует

// корректную инфраструктуру для выражений запросов!

public abstract class Array : ICloneable, IList,

  IStructuralComparable, IStructuralEquatable

{

  ...

}

Хотя класс

System.Array
не реализует напрямую интерфейс
IEnumerable&lt;T&gt;
, он косвенно получает необходимую функциональность данного типа (а также многие другие члены, связанные с LINQ) через статический тип класса
System.Linq.Enumerable
.

В служебном классе

System.Linq.Enumerable
определено множество обобщенных расширяющих методов (таких как
Aggregate&lt;T&gt;()
,
First&lt;T&gt;()
,
Мах&lt;Т&gt;()
и т.д.), которые класс
System.Array
(и другие типы) получают в свое распоряжение на заднем плане. Таким образом, если вы примените операцию точки к локальной переменной
currentVideoGames
, то обнаружите большое количество членов, которые отсутствуют в формальном определении
System.Array

Роль отложенного выполнения

Еще один важный момент, касающийся выражений запросов LINQ, заключается в том, что фактически они не оцениваются до тех пор, пока не начнется итерация по результирующей последовательности. Формально это называется отложенным выполнением. Преимущество такого подхода связано с возможностью применения одного и того же запроса LINQ многократно к тому же самому контейнеру и полной гарантией получения актуальных результатов. Взгляните на следующее обновление метода

QueryOverlnts()
:

static void QueryOverInts()

{

  int[] numbers = { 10, 20, 30, 40, 1, 2, 3, 8 };

  // Получить числа меньше 10.

  var subset = from i in numbers where i &lt; 10 select i;

<b>  // Оператор LINQ здесь оценивается!</b>

  foreach (var i in subset)

  {

    Console.WriteLine(&quot;{0} &lt; 10&quot;, i);

  }

  Console.WriteLine();

  // Изменить некоторые данные в массиве.

  numbers[0] = 4;

<b>  // Снова производится оценка!</b>

  foreach (var j in subset)

  {

    Console.WriteLine(&quot;{0} &lt; 10&quot;, j);

  }

  Console.WriteLine();

  ReflectOverQueryResults(subset);

}

На заметку! Когда оператор LINQ выбирает одиночный элемент (с использованием

First()/FirstOrDefault()
,
Single()/SingleOrDefault()
или любого метода агрегирования), запрос выполняется немедленно. Методы
First()
,
FirstOrDefault()
,
Single()
и
SingleOrDefault
будут описаны в следующем разделе. Методы агрегирования раскрываются позже в главе.

Ниже показан вывод, полученный в результате запуска программы. Обратите внимание, что во второй итерации по запрошенной последовательности появился дополнительный член, т.к. для первого элемента массива было установлено значение меньше 10:

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*