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

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

Возвращаемое значение метода

Where
в приведенном примере кода скрыто от глаз, но "за кулисами" работа происходит с типом
OrderedEnumerable
. На объекте указанного типа вызывается обобщенный метод
OrderBy
, который также принимает параметр типа делегата
Func<>
. Теперь производится передача всех элементов по очереди посредством подходящего лямбда-выражения. Результатом вызова
OrderBy
является новая упорядоченная последовательность первоначальных данных.

И, наконец, осуществляется вызов метода

Select
на последовательности, возвращенной
OrderBy
,
который в итоге дает финальный набор данных, сохраняемый в неявно типизированной переменной по имени
subset
.

Конечно, такой "длинный" запрос LINQ несколько сложнее для восприятия, чем предыдущий пример с операциями запросов LINQ. Без сомнения, часть сложности связана с объединением в цепочку вызовов посредством операции точки. Вот тот же самый запрос с выделением каждого шага в отдельный фрагмент (разбивать запрос на части можно разными способами):

static void QueryStringsWithEnumerableAndLambdas2

{

Console.WriteLine("***** Using Enumerable / Lambda Expressions *****");

string[] currentVideoGames = {"Morrowind", "Uncharted 2",

"Fallout 3", "Daxter", "System
Shock 2"};

// Разбить на части.

var gamesWithSpaces =

currentVideoGames.Where(game => game.Contains(" "));

var orderedGames = gamesWithSpaces.OrderBy(game => game);

var subset = orderedGames.Select(game => game);

foreach (var game in subset)

{

Console.WriteLine("Item: {0}", game);

}

Console.WriteLine;

}

Как видите, построение выражения запроса LINQ с применением методов класса

Enumerable
напрямую приводит к намного более многословному запросу, чем в случае использования операций запросов С#. Кроме того, поскольку методы
Enumerable
требуют передачи делегатов в качестве параметров, обычно необходимо писать лямбда-выражения, чтобы обеспечить обработку входных данных внутренней целью делегата.

Построение выражений запросов с использованием типа Enumerable и анонимных методов

Учитывая, что лямбда-выражения C# — это просто сокращенный способ работы с анонимными методами, рассмотрим третье выражение запроса внутри вспомогательного метода

QueryStringsWithAnonymousMethods
:

static void QueryStringsWithAnonymousMethods

{

Console.WriteLine("***** Using Anonymous Methods *****");

string[] currentVideoGames = {"Morrowind", "Uncharted 2",

"Fallout 3", "Daxter", "System
Shock 2"};

// Построить необходимые делегаты Func<>

// с использованием анонимных методов.

Func<string, bool> searchFilter =

delegate(string game) { return game.Contains(" "); };

Func<string, string> itemToProcess = delegate(string s) { return s; };

//
Передать делегаты в методы класса Enumerable.

var subset =

currentVideoGames.Where(searchFilter).OrderBy(itemToProcess).

Select(itemToProcess);

// Вывести результаты.

foreach (var game in subset)

{

Console.WriteLine("Item: {0}", game);

}

Console.WriteLine;

}

Такой вариант выражения запроса оказывается еще более многословным из-за создания вручную делегатов

Func<>
, применяемых методами
Where
,
OrderBy
и
Select
класса
Enumerable
. Положительная сторона данного подхода связана с тем, что синтаксис анонимных методов позволяет заключить всю обработку, выполняемую делегатами, в единственное определение метода. Тем не менее, этот метод функционально эквивалентен методам
QueryStringsWithEnumerableAndLambdas
и
QueryStringsWithOperators
, созданным в предшествующих разделах.

Построение выражений запросов с использованием типа Enumerable и низкоуровневых делегатов

Наконец, если вы хотите строить выражение запроса с применением многословного подхода, то можете отказаться от использования синтаксиса лямбда-выражений и анонимных методов и напрямую создавать цели делегатов для каждого типа

Func<>
. Ниже показана финальная версия выражения запроса, смоделированная внутри нового типа класса по имени
VeryComplexQueryExpression
:

class VeryComplexQueryExpression

{

public static void QueryStringsWithRawDelegates

{

Console.WriteLine("***** Using Raw Delegates *****");

string[] currentVideoGames = {"Morrowind", "Uncharted 2",

"Fallout 3", "Daxter", "System
Shock 2"};

// Построить необходимые делегаты Func<>.

Func<string, bool> searchFilter =

new Func<string, bool>(Filter);

Func<string, string> itemToProcess =

new Func<string,string>(ProcessItem);

// Передать делегаты в методы класса Enumerable.

var subset =

currentVideoGames

.Where(searchFilter)

.OrderBy(itemToProcess)

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