KnigaRead.com/
KnigaRead.com » Разная литература » Прочее » Герберт Шилдт - C# 4.0 полное руководство - 2011

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

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн "Герберт Шилдт - C# 4.0 полное руководство - 2011". Жанр: Прочее издательство неизвестно, год неизвестен.
Перейти на страницу:

Ниже приведен результат выполнения этой программы. Обратите особое внимание на суммарное значение.

0

1

2

3

Сумма 3 равна 6

0

1

2

3

4

5

Сумма 5 равна 21

Как видите, подсчет по-прежнему выполняется как обычно. Но обратите внимание на то, что сумма 5 теперь равна 21, а не 15! Дело в том, что переменная sum захватывается объектом ctOb j при его создании в методе Counter (). Это означает, что она продолжает существовать вплоть до уничтожения делегата count при "сборке мусо-ра" в самом конце программы. Следовательно, ее значение не уничтожается после возврата из метода Counter () или при каждом вызове анонимного метода, когда происходит обращение к делегату count в методе Main ().

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

Лямбда-выражения

Несмотря на всю ценность анонимных методов, им на смену пришел более совершенный подход: лямбда-выражение. Не будет преувеличением сказать, что лямбда-выражение относится к одним из самых важных нововведений в С#, начиная с выпуска исходной версии 1.0 этого языка программирования. Лямбда-выражение основывается на совершенно новом синтаксическом элементе и служит более эффективной альтернативой анонимному методу. И хотя лямбда-выражения находят применение главным образом в работе с LINQ (подробнее об этом — в главе 19), они часто используются и вместе с делегатами и событиями. Именно об этом применении лямбда-выражений и пойдет речь в данном разделе.

Лямбда-выражение — это другой собой создания анонимной функции. (Первый ее способ, анонимный метод, был рассмотрен в предыдущем разделе.) Следовательно, лямбда-выражение может быть присвоено делегату. А поскольку лямбда-выражение считается более эффективным, чем эквивалентный ему анонимный метод, то в большинстве случаев рекомендуется отдавать предпочтение именно ему.

Лямбда-оператор

Во всех лямбда-выражениях применяется новый лямбда-оператор =>, который разделяет лямбда-выражение на две части. В левой его части указывается входной параметр (или несколько параметров), а в правой части — тело лямбда-выражения. Оператор => иногда описывается такими словами, как "переходит" или "становится".

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

Одиночные лямбда-выражения

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

Ниже приведена общая форма одиночного лямбда-выражения, принимающего единственный параметр.

параметр => выражение

Если же требуется указать несколько параметров, то используется следующая форма.

(список_параметров) => выражение

Таким образом, когда требуется указать два параметра или более, их следует заключить в скобки. Если же выражение не требует параметров, то следует использовать пустые скобки.

Ниже приведен простой пример одиночного лямбда-выражения.

count- => count + 2

В этом выражении count служит параметром, на который воздействует выражение count + 2. В итоге значение параметра count увеличивается на 2. А вот еще один пример одиночного лямбда-выражения.

n => п % 2 == О

В данн“ом случае выражение возвращает логическое значение true, если числовое значение параметра п оказывается четным, а иначе — логическое значение false.

Лямбда-выражение применяется в два этапа. Сначала объявляется тип делегата, совместимый с лямбда-выражением, а затем экземпляр делегата, которому присваивается лямбда-выражение. После этого лямбда-выражение вычисляется при обращении к экземпляру делегата. Результатом его вычисления становится возвращаемое значение.

В приведенном ниже примере программы демонстрируется применение двух одиночных лямбда-выражений. Сначала в этой программе объявляются два типа делегатов. Первый из них, Inc г, принимает аргумент типа int и возвращает результат того же типа. Второй делегат, IsEven, также принимает аргумент типа int, но возвращает результат типа bool. Затем экземплярам этих делегатов присваиваются одиночные лямбда-выражения. И наконец, лямбда-выражения вычисляются с помощью соответствующих экземпляров делегатов.

// Применить два одиночных лямбда-выражения.

11 Объявить делегат, принимающий аргумент типа int и // возвращающий результат типа int.    '

delegate int Incr(int v);

// Объявить делегат, принимающий аргумент типа int и // возвращающий результат типа bool, delegate bool IsEven(int v);

class SimpleLambdaDemo {

static void Main() {

// Создать делегат Incr, ссылающийся на лямбда-выражение,

// увеличивающее свой параметр на 2.

Incr incr = count => count + 2;

// А теперь использовать лямбда-выражение incr.

Console.WriteLine("Использование лямбда-выражения incr: "); int x = -10; while(x <= 0)    {

Console.Write(x + " ");

x = incr(x); // увеличить значение x на 2

}

Console.WriteLine ("n");

// Создать экземпляр делегата IsEven, ссылающийся на лямбда-выражение,

// возвращающее логическое значение true, если его параметр имеет четное // значение, а иначе — логическое значение false.

IsEven isEven = n => n % 2 == 0;

// А теперь использовать лямбда-выражение isEven.

Console.WriteLine("Использование лямбда-выражения isEven: "); for (int i=l; i <= 10; i++)

if(isEven (i)) Console.WriteLine(i + " четное.");

}

}

Вот к какому результату приводит выполнение этой программы.

Использование лямбда-выражения incr:

-10 -8 -6 -4 -2 0

Использование лямбда-выражения isEven:

2 четное.

4 четное.

6 четное.

8 четное.

10 четьюе.

Обратите в данной программе особое внимание на следующие строки объявлений.

Incr incr = count => count +2;

IsEven isEven = n => n % 2 == 0;

В первой строке объявления экземпляру делегата incr присваивается одиночное лямбда-выражение, возвращающее результат увеличения на 2 значения параметра count. Это выражение может быть присвоено делегату Incr, поскольку оно совместимо с объявлением данного делегата. Аргумент, указываемый при обращении к экземпляру делегата incr, передается параметру count, который и возвращает результат вычисления лямбда-выражения. Во второй строке объявления делегату isEven присваивается выражение, возвращающее логическое значение true, если передаваемый ему аргумент оказывается четным, а иначе — логическое значение false. Следовательно, это лямбда-выражение совместимо с объявлением делегата IsEven.

В связи со всем изложенным выше возникает резонный вопрос: каким образом компилятору становится известно о типе данных, используемых в лямбда-выражении, например, о типе int параметра count в лямбда-выражении, присваиваемом экземпляру делегата incr? Ответить на этот вопрос можно так: компилятор делает заключение о типе параметра и типе результата вычисления выражения по типу делегата. Следовательно, параметры и возвращаемое значение лямбда-выражения должны быть совместимы по типу с параметрами и возвращаемым значением делегата.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*