Чтение онлайн

ЖАНРЫ

C# 4.0 полное руководство - 2011

Шилдт Герберт

Шрифт:

К категории <Речной транспорт> относится: лодка каноэ

Главной частью данной программы, безусловно, является следующий запрос.

var byHow = from how in travelTypes

join trans in transports on how equals trans.How into 1st

select new { How = how, Tlist = 1st };

Этот запрос формируется следующим образом. В операторе from используется переменная диапазона how для охвата всего массива travelTypes. Напомним, что массив travelTypes содержит названия общих категорий транспорта: воздушного, наземного, морского и речного. Каждый вид транспорта объединяется в операторе join со своей категорией. Например, велосипед, автомашина и поез^объедйняются с наземным транспортом. Но благодаря оператору into для каждой категории транспорта в операторе join составляется

список видов транспорта, относящихся к данной категории. Этот список сохраняется в переменной
1st. И наконец, оператор select возвращает объект анонимного типа, инкапсулирующий каждое значение переменной how (категории транспорта) вместе со списком видов транспорта. Именно поэтому для вывода результатов запроса требуются два цикла foreach.

foreach(var t in byHow) {

Console.WriteLine("К категории <{0} транспорт> относится:", t.How);

foreach(var m in t.Tlist)

Console.WriteLine(" " + m.Name);

Console.WriteLine;

}

Во внешнем цикле получается объект, содержащий наименование общей категории транспорта, и список видов транспорта, относящихся к этой категории. А во внутреннем цикле выводятся отдельные виды транспорта.

Методы запроса

Синтаксис запроса, описанный в предыдущих разделах, применяется при формировании большинства запросов в С#. Он удобен, эффективен и компактен, хотя и не является единственным способом формирования запросов. Другой способ состоит в использовании методов запроса, которые могут вызываться для любого перечислимого объекта, например массива.

Основные методы запроса

Методы запроса определяются в классе System. Linq. Enumerable и реализуются в виде методов расширения функций обобщенной формы интерфейса IEnumerable<T>. (Методы запроса определяются также в классе System. Linq. Queryable, расширяющем функции обобщенной формы интерфейса IQueryable<T>, но этот интерфейс в настоящей главе не рассматривается.) Метод расширения дополняет функции другого класса, но без наследования. Поддержка методов расширения была внедрена в версию C# 3.0 и более подробно рассматривается далее в этой главе. А до тех пор достаточно сказать, что методы запроса могут вызываться только для тех объектов, которые реализуют интерфейс IEnumerable<T>.

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

Оператор запроса

Эквивалентный метод запроса

select

Select(selector)

where

Where(predicate)

orderby

OrderBy(keySelector) или OrderByDescending(keySelector)

join

Join(inner, outerKeySelector, innerKeySelector, resultSelector)

group

GroupBy(keySelector)

За исключением метода Join , остальные методы запроса принимают единственный аргумент, который представляет собой

объект некоторой разновидности обобщенного типа
Func<T, TResultx Это тип встроенного делегата, объявляемый следующим образом:

delegate TResult Funccin Т, out TResult>(Т arg)

где TResult обозначает тип результата, который дает делегат, а Т — тип элемента. В методах запроса аргументы selector, predicate или keySelector определяют действие, которое предпринимает метод запроса. Например, в методе Where аргумент predicate определяет порядок отбора данных в запросе. Каждый метод запроса возвращает перечислимый объект. Поэтому результат выполнения одного метода запроса можно использовать для вызова другого, соединяя эти методы в цепочку.

Метод Join принимает четыре аргумента. Первый аргумент (inner) представляет собой ссылку на вторую объединяемую последовательность, а первой является последовательность, для которой вызывается метод Join . Селектор ключа для первой последовательности передается в качестве аргумента outerKeySelector, а селектор ключа для второй последовательности — в качестве аргумента innerKeySelector. Результат объединения обозначается как аргумент resultSelector. Аргумент outerKeySelector имеет тип Func<T0uter, ТКеу>, аргумент innerKeySelector — тип Func<TInner, ТКеу>, тог^а как аргумент resultSelector — тип Func<T0uter, Tinner, TResult>, где TOuter — тип элемента из вызывающей последовательности; Tinner — тип элемента из передаваемой последовательности; TResult — тип элемента из объединяемой в итоге последовательности, возвращаемой в виде перечислимого объекта.

Аргумент метода запроса представляет собой метод, совместимый с указываемой формой делегата Fun с, но он не обязательно должен быть явно объявляемым методом. На самом деле вместо него чаще всего используется лямбда-выражение. Как пояснялось в главе 15, лямбда-выражение обеспечивает более простой, но эффективный способ определения того, что, по существу, является анонимным методом, а компилятор C# автоматически преобразует лямбда-выражение в форму, которая может быть передана в качестве параметра делегату Fun с. Благодаря тому что лямбда-выражения обеспечивают более простой и рациональный способ программирования, они используются во всех примерах, представленных далее в этом разделе.

Формирование запросов с помощью методов запроса

Используя методы запроса одновременно с лямбда-выражениями, можно формировать запросы, вообще не пользуясь синтаксисом, предусмотренным в C# для запросов. Вместо этого достаточно вызвать соответствующие методы запроса. Обратимся сначала к простому примеру. Он представляет собой вариант первого примера программы из этой главы, переделанный с целью продемонстрировать применение методов запроса Where и Select вместо соответствующих операторов.

// Использовать методы запроса для формирования простого запроса.

// Это переделанный вариант первого примера программы из настоящей главы.

using System; using System.Linq;

class SimpQuery {

static void Main {

int[] nums = { 1, -2, 3, О, -4, 5 };

// Использовать методы Where и Select для // формирования простого запроса.

var posNums = nums.Where(n => n > 0).Select(r => r);

Поделиться с друзьями: