|
Программирование >> Программирование с использованием ajax
В методе Main () создаются три лямбда-выражения, которые затем по очереди используются для вызова метода PerformOperations (). Первый из этих вызовов выглядит следующим образом: Console.WriteLine( f(а, b) = а + b: ); PerformOperations((paramA, paramB) => paramA + paramB); Лямбда-выражением здесь является: (paramA, paramB) => paramA + paramB Опять-таки, oho делится на три описанных ниже части. 1. Раздел определения параметров. Здесь определены два параметра - paramA и paramB. Они являются не типизированными, а это значит, что компилятор может выводить типы этих параметров из контекста. В данном случае он может определить, что вызов метода PerformOperations () требует использования делегата типа TwoIntegerOperationDelegate. У этого типа делегата имеется два параметра int, так что путем выведения получается, что типом и paramA, и paramB является int. 2. Операция =>. Она просто отделяет параметры от тела лямбда-выражения. 3. Тело выражения. Здесь задается простая операция, подразумевающая суммирование параметров paramA и paramB. Обратите внимание на то, что указывать, что это является возвращаемым значением, нет никакой необходимости. Компилятору известно о том, что для создания метода, пригодного для использования TwoIntegerOperationDelegate, необходимо, чтобы его возвращаемым типом был int. Поскольку заданная операция - paramA+paramB - вычисляется в int, и никакой дополнительной информации не предоставляется, компилятор понимает, что результатом данного выражения должен быть возвращаемый тип метода. В длинном варианте тогда код, в котором используется это лямбда-выражение, можно было бы расширить до следующего кода, в котором используется уже анонимный метод: Console.WriteLine( f(а, b) = а + b: ); PerformOperations (delegate (int paraxnA, int paramB) { return paramA + paramB; В остальной части кода выполняются операции с использованием двух разных лямбда-выражений одинаковым образом: Console.WriteLine() ; Console.WriteLine( f(а, b) = а * b: ); PerformOperations((paramA, paramB) => paramA * paramB); Console.WriteLine(); Console.WriteLine( f(a, b) = (a - b) % b: ); PerformOperations((paramA, paramB) => (paramA - paramB) % paramB); Console.ReadKey 0; Последнее лямбда-выражение подразумевает больше вычислений, но сложнее других от этого не становится. Синтаксис лямбда-выражений позволяет выполнять и гораздо более сложные операции, как будет показано ниже. Параметры лямбда-выражений в коде, который демонстрировался до сих пор, в лямбда-выражениях для определения типов передаваемых параметров применялся механизм выведения типов. На самом деле, обязательным это не является; при желании типы параметров можно и определять. Например, можно было бы использовать и такое лямбда-выражение: (int paramA, int paramB) => paramA + paramB При таком подходе код получается более удобочитаемым, но утрачивает краткость и гибкость. Лямбда-выражения с неявным определением типов из предыдущего практического занятия можно было бы использовать для типов делегатов с другими числовыми типами, например, long. Обратите внимание на то, что использовать и неявные и явные типы параметров в одном и том же лямбда-выражении нельзя. Следующее лямбда-выражение компилироваться не будет, потому что тип параметра paramA в нем определяется явно, а параметра paramB - неявно: (int paramA, paramB) => paramA + paramB Списки параметров в лямбда-выражениях всегда состоят из разделенного запятыми перечня либо всех неявно типизированных, либо всех явно типизированных параметров. Если параметр только один, тогда круглые скобки могут опускаться; в противном случае они являются обязательной частью списка параметров, как в показанном выше примере. Например, лямбда-выражение с единственным неявно типизированным параметром может выглядеть так: paraml => paraml * paraml Еще можно определять лямбда-выражения, не имеющие параметров. Отсутствие параметров обозначается пустыми круглыми скобками, как показано ниже: О => Math.PI Такое выражение могло бы пригодиться при необходимости в использовании делегата, не требующего никаких параметров, но возвращающего значение double. Тело операторов лямбда-выражений Во всем приводившемся пока что коде в теле оператора лямбда-выражений использовалось единственное выражение. Это выражение воспринималось как возвращаемое значение лямбда-выражения, что и показывает то, как, к примеру, выражение paramA + paramB можно применять в качестве тела оператора для лямбда-выражения, предназначенного для делегата с возвращаемым типом int (при условии приведения обоих параметров paramA и paramB явным или неявным образом к int, как это и было сделано в примере кода). Еще в одном из прежних примеров было показано, как делегат с возвращаемым типом void позволяет использовать менее громоздкий код в теле оператора: myTimer.Elapsed += (source, е) => Console.WriteLine ( Event handler called after {0} milliseconds. , (source as Timer).Interval); Здесь оператор ни во что не вычисляется, и потому будет выполняться без использования возвращаемого значения. С учетом того, что лямбда-выражения могут визуализироваться в виде расширения синтаксиса анонимных методов, вряд ли покажется удивительным то, что в виде части тела операторов лямбда-выражений можно также использовать и множество операторов. Осуществляется это путем предоставления заключенного в фигурные скобки кода, во многом подобно тому, как это делается в любых других ситуациях в С#, когда требуется предоставлять несколько строк кода: (paraml, param2) => { Здесь идет несколько операторов. В случае использования лямбда-выражения в сочетании с делегатом, возвращаемым типом которого является не void, нужно обязательно выполнять возврат значения с помощью ключевого слова return, точно так же как и в любом другом методе: (paraml, param2) => { Здесь идет несколько операторов! return возвращаемое значение; Например, ранее уже показывалось, что следующий код из практического занятия: PerformOperations((paramA, paramB) => paramA + paramB); МОЖНО было бы переписать так: PerformOperations(delegate(int paramA, int paramB) { return paramA + paramB; В качестве альтернативного варианта, этот код можно было бы переписать и следующим образом: PerformOperations((рагашА, paramB) => return paramA + paramB; В этом случае достигается большая преемственность с исходным кодом, поскольку сохраняется неявная типизация параметров paramA и paramB. По большей части лямбда-выражения наиболее полезными и, конечно же, наиболее элегантными, являются тогда, когда используются с одним выражением. Честно говоря, при наличии необходимости в добавлении нескольких операторов код может читаться гораздо лучше, если вместо лямбда-выражения применить отдельный не анонимный метод; это еще также сделает его и более пригодным для многократного использования. Лямбда-выражения как делегаты и как деревья выражений Некоторые отличия между лямбда-выражениями и анонимными методами, вроде того, что лямбда-методы обладают большей гибкостью (например, могут иметь неявно типизированные параметры), уже были показаны. Теперь пришла пора рассказать о еще одном важном отличии, последствия которого, однако, прояснятся лишь позже в книге, при изучении технологии LINQ. Лямбда-выражения можно интерпретировать двумя способами. Первый способ, который демонстрировался повсюду в этой главе, позволяет интерпретировать их в качестве делегата. То есть он позволяет присваивать лямбда-выражение переменной типа делегата, как это и делалось в предыдущем практическом занятии.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |