|
Программирование >> Программирование с использованием ajax
В общих чертах это означает, что лямбда-выражение с параметрами в количестве вплоть до четырех можно представлять в виде одного из следующих обобщенных типов, все их которых определены в пространстве имен 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/..
Рис. 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) ) ;
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |