Программирование >>  Программирование с использованием ajax 

1 ... 133 134 135 [ 136 ] 137 138 139 ... 396


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

□ Actiono для лямбда-выражений без параметров и с возвращаемым типом

void.

□ Actiono для лямбда выражений с параметрами в количестве вплоть до четырех и возвращаемым типом void.

□ Funco для лямбда-выражений с параметрами в количестве вплоть до четырех и возвращаемым типом, который не является типом void.

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

Например, следующее лямбда-выражение (которое уже приводилось ранее):

(int paramA, int paramB) => paramA + paramB

может быть представлено в виде делегата типа Func<int, int, int>, поскольку у него есть всегда два параметра и их типом вместе с возвращаемым типом является int.

Второй способ позволяет интерпретировать лямбда-выражение как дерево выражения (expression tree). Дерево выражения является абстрактным представлением лямбда-выражения и как таковое не может выполняться напрямую. Вместо этого его можно использовать для программного анализа лямбда-выргокения и выполнения в ответ на него различных действий.

Очевидно, что данная тема является сложной. Но деревья выражений играют критически важную роль в функциональных возможностях LINQ. Чтобы привести более конкретный пример, скажем, что в состав каркаса LINQ входит обобщенный класс по имени Expressiono, который можно использовать для инкапсуляции лямбда-выражения. Один из способов применения этого класса выглядит так: взять лямбда-выражение, которое было написано разработчиком на С#, и преобразовать его в эквивалентный сценарий на языке SQL, пригодный для выполнения прямо в базе данных.

На данном этапе больше ничего знать не требуется. Теперь, когда эта функциональная возможность будет встречаться далее в книге, вы сможете понять, что происходит, поскольку в этой главе были предоставлены сведения о ключевых концепциях, предлагаемых С# 3.0.

Лямбда-выражения и коллекции

Сейчас, когда уже было рассказано об обобщенном делегате Funco, можно переходить к рассмотрению других методов расширения, которые предлагаются в пространстве имен System. Linq для типов-массивов. Например, там есть метод расширения Aggregate (), определение которого включает три перегрузки:

public static TSource Aggregate<TSource>( this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func);

public static TAccumulate Aggregate<TSource, TAccumulate>( this IEnumerable<TSource> source, TAccumulate seed,

Func<TAccumulate, TSource, TAccumulate> func);



public static TResult Aggregate<TSource, TAccumulate, TResult> ( this IEnumerable<TSource> source, TAccumulate seed,

Func<TAccumulate, TSource, TAccumulate> func, Func<TAccumulate, TResult> resultSelector);

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

Applies an accumulator function over a sequence. Применяет аккумулирующую функцию к последовательности.

Это означает, что аккумулирующая функция (которая может предоставляться в виде лямбда-выражения) будет применяться для каждой пары элементов в коллекции от начала до конца с превращением выходных данных каждой операции вычисления во входные данные следующей операции вычисления.

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

int[] mylntArray = {2, 6, 3};

int result = mylntArray.Aggregate (...);

Этот код эквивалентен следующему:

int[] mylntArray = {2, 6, 3};

int result = my IntArray. Aggregate < int > (...);

Требуемое лямбда-выражение здесь может быть выведено из спецификации метода расширения. Поскольку в этом коде типом TSource является int, лямбда-выражение должно иметь вид делегата Func<int, int, int>. Например, это может быть и лямбда-выражение, которое уже демонстрировалось ранее:

int[] mylntArray = {2, 6, 3};

int result = mylntArray.Aggregate ((paramA, paramB) => paramA + paramB) ;

Такой вызов приведет к тому, что лямбда-выражение будет вызвано дважды: первый раз с параметром paramA равным 2 и параметром paramB равным 6, а второй - с параметром paramA равным 8 (в результате первого вычисления) и параметром paramB равным 3. В конечном результате переменной result будет присвоено int-значение 11, являющееся суммой значений всех элементов в массиве.

Две других перегрузки метода расширения Aggregate () выглядят похоже, но позволяют выполнять немного более сложные операции по обработке и детально иллюстрируются в следующем практическом занятии.

JJggSSli*!J Лямбда-выражения и коллекции

1. Создайте новое консольное приложение по имени Chl4Ex05 и сохраните его в каталоге С:\BegVCSharp\Chapterl4.

2. Измените код в его файле Program.cs следующим образом:

static void Main(string [ ] args) {

string[] curries = { pathia , jalfreze , korma }; Console.WriteLine (curries .Aggregate ( (a, b) => a + + b) );



Console.WriteLine(curries.Aggregate < string, int > ( 0,

(a, b) => a + b. Length) ) ; Console.WriteLine(curries.Aggregate < string, string, string > ( Some curries: , (a, b) => a + + b, a => a)) ;

Console.WriteLine(curries.Aggregate < string, string, int > (

Some curries: ,

(a, b) => a + + b,

a => a.Length)); Console.ReadKey ();

3. Запустите приложение. На рис. 14.11 показан результат, который должен получиться.

I rite У/АС /B*gVCSharprt:hapter14/Ch14Ex05/..

IMtlliA

Jnlfrei когп.

urrir:.: pathia

Jalfrezi ко

Рис. 14.11. Приложение Chi 4 Ex О 5 в действии

Описание полученных результатов

Этот пример демонстрирует применение каждой из трех перегрузок такого метода расширения, как Aggregate (), с использованием в качестве исходных данных строкового массива с тремя элементами.

Сначала выполняется простая конкатенация:

Console.WriteLine(curries.Aggregate( (а, b) => а + + b) ) ;

Первая пара элементов путем конкатенации превращается в одну строку с помощью простого синтаксиса. Такой синтаксис далеко не является лучшим для конкатенации строк - в идеале вместо него для достижения оптимальной производительности следовало бы использовать либо метод string. Concat (), либо метод string. Format () - но здесь он позволяет очень легко увидеть, что происходит. После этой первой операции конкатенации результат передается обратно лямбда-выражению вместе с третьим элементом массива во многом подобно тому, как это происходило при суммировании значений int, которое показывалось ранее. Это в конечном итоге приводит к конкатенации всего массива с разделением его элементов пробелами.

Далее применяется вторая перегрузка функции Aggregate (), в которой предусмотрены два параметра обобщенного типа - TSource и TAccumulate. В таком случае лямбда-выражение должно иметь вид Func<TAccumulate, TSource, TAccumulate>. Вдобавок, еще должно быть указано и начальное значение типа TAccumulate. Это начальное значение используется в первом вызове лямбда-выражения вместе с первым элементом массива. В последующих вызовах берется аккумулированный результат предыдущих вызовов этого выражения. Код, который использовался в данном примере, выглядит следующим образом:

Console.WriteLine(curries.Aggregate<string, int>( О,

(a, b) => a + b.Length) ) ;



1 ... 133 134 135 [ 136 ] 137 138 139 ... 396

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки.
Яндекс.Метрика