Отношения между типами в операциях запросов LINQ (C#)
Для эффективного написания запросов следует понимать, как типы переменных связаны друг с другом в полной операции запроса.Понимание этих связей облегчит усвоение примеров LINQ и примеров кода в документации.Более того, можно будет представить, что происходит в фоновом режиме при неявном типизировании переменных с помощью var.
Операции запросов LINQ строго типизированы в источнике данных, в самом запросе и при выполнении запроса.Тип переменных в запросе должен быть совместим с типом элементов в источнике данных и с типом переменной итерации в операторе foreach.Строгая типизация гарантирует перехват ошибок во время компиляции, когда их можно будет исправить прежде, чем с ними столкнутся пользователи.
Для демонстрации связи типов большая часть примеров использует явную типизацию для всех переменных.Последний пример показывает применение тех же принципов даже при использовании неявной типизации с помощью var.
Запросы, не выполняющие преобразование исходных данных
На следующем рисунке показана операция запроса LINQ to Objects, не выполняющая преобразование данных.Источник содержит последовательность строк, результат запроса также является последовательностью строк.
Аргумент типа источника данных определяет тип переменной диапазона.
Тип выбранного объекта определяет тип переменной запроса.Здесь name является строкой.Следовательно, переменная запроса является IEnumerable<string>.
Итерация переменной запроса выполняется в операторе foreachПоскольку переменная запроса является последовательностью строк, переменная итерации также является строкой.
Запросы, выполняющие преобразование исходных данных
На следующем рисунке показана операция запроса LINQ to SQL, выполняющая простое преобразование данных.В качестве входных данных запрос получает последовательность объектов Customer и выбирает в результате только свойство Name.Поскольку Name является строкой, запрос создает последовательность строк в качестве выходных данных.
Аргумент типа источника данных определяет тип переменной диапазона.
Оператор select возвращает свойство Name вместо целого объекта Customer.Поскольку Name является строкой, аргумент типа custNameQuery является string, а не Customer.
Поскольку custNameQuery является последовательностью строк, переменная итерации цикла foreach также должна быть string.
На следующем рисунке показано немного более сложное преобразование.Оператор select возвращает анонимный тип, захватывающий только два члена исходного объекта Customer.
Аргумент типа источника данных всегда является типом переменной диапазона в запросе.
Так как оператор select создает анонимный тип, переменная запроса должна быть неявно типизирована с помощью var.
Поскольку тип переменной запроса неявный, переменная итерации в цикле foreach также должна быть неявной.
Разрешение компилятору определять сведения о типе
Несмотря на то, что необходимо обладать знаниями об отношениях типов в операции запроса, существует возможность передачи выполнения всех действий компилятору.Ключевое слово var можно использовать для любой локальной переменной в операции запроса.Следующий рисунок аналогичен примеру 2, рассмотренному выше.Единственным отличием является то, что компилятор будет указывать строгий тип для каждой переменной в операции запроса.
Дополнительные сведения о var см. в разделе Неявно типизированные локальные переменные (Руководство по программированию в C#).
См. также
Основные понятия
Отношения типов в операциях запроса (Visual Basic)