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

1 ... 131 132 133 [ 134 ] 135 136 137 ... 396


Компилятору С# известен тип делегата, который требуется событию Elapsed, поэтому он сможет самостоятельно добавить все недостающие сведения. Однако в большинстве случаев поступать подобным образом все же не рекомендуется, поскольку такой подход затрудняет чтение кода и не позволяет видеть, что именно в нем происходит. При использовании анонимного метода приведенная выше последовательность шагов сокращается до одного единственного шага, который выглядит следующим образом.

1. Использовать внутристрочный анонимный метод с возвращаемым типом и параметрами, соответствующими возвращаемому типу и параметрам делегата, который требуется для подписываемого события.

Определяется внутристрочный анонимный метод с использованием ключевого слова delegate:

myTimer.Elapsed += delegate(object source, ElapsedEventArgs e) {

Console.WriteLine( Event handler called after {0} milliseconds. , (source as Timer).Interval);

Этот код будет работать так же хорошо, как и отдельный обработчик. Главное отличие состоит в том, что использованный здесь анонимный метод будет фактически скрыт от остальной части кода. То есть, например, применять этот обработчик повторно в другом месте приложения не получится. Кроме того, примененный здесь синтаксис является, мягко говоря, несколько громоздким. Ключевое слово delegate сразу же сбивает с толку, поскольку оно, в сущности, перегружается, так как используется и для определения анонимных методов, и для определения типов делегатов.

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

Мы подошли, наконец, непосредственно к самим лямбда-выражениям. Лямбда-выражения являются способом упрощения синтаксиса анонимных методов. На самом деле они являются не только этим, но давайте пока не будем усложнять дело. С помощью лямбда-выражения код, который был приведен в конце предыдущего раздела, можно переписать следующим образом:

myTimer.Elapsed += (source, е) => Console.WriteLine(

Event handler called after {0} milliseconds. , (source as Timer).Interval);

Ha первый взгляд это выражение выглядит несколько устрашающе (если только вы не знакомы с так называемыми языками функционального программирования вроде Lisp или Haskell, например). Однако если получше к нему присмотреться, то можно увидеть или, по крайней мере, догадаться, каким образом оно работает и какое отношение имеет к тому анонимному методу, который собой заменяет. Состоит оно из трех частей:

□ список (нетипизированных) параметров в круглых скобках;

□ операция =>;

□ оператор на языке С#.

Типы параметров будут выводиться из контекста с применением той же самой логики, которая демонстрировалась в разделе Анонимные типы ранее в главе. Операция => просто отделяет список параметров от тела выражения, которое будет выполняться при вызове лямбда-выражения.



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

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

Практическое занятЦЦР

Простые лямбда-выражения

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

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

namespace Chl4Ex04 {

delegate int TwoIntegerOperationDelegate (int paramA, int paramB);

class Program {

static void PerformOperations(TwoIntegerOperationDelegate del) (

for (int paramAVal = 1; paramAVal <= 5; paramAVal++) {

for (int paramBVal = 1; paramBVal <= 5; paramBVal++) {

int delegateCallResult = del(paramAVal, paramBVal); Console.Write( f(I 0},{1})={2} ,

paramAVal, paramBVal, delegateCallResult);

if (paramBVal != 5)

Console.WriteC, );

Console.WriteLine();

static void Main(string[] args) {

Console.WriteLine( f(a, b) = a + b: );

PerformOperations((paramA, paramB) => paramA + paramB); Console.WriteLine() ;

Console.WriteLine( f(a, b) = a * 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;

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



I fi*e /;,CJBeflVCSh nvChapt r14/Ch14Ex04.4:h14lx04rt m/.-

f<l,l> 2, f<l,2> 3,

f<2.1> 3. f<2,2> 1,

f<3,l> 4. f<3,2> 5.

1<4Л> 5, f<4,2> b,

f<5,l> 6. f<5,2> 7.

K,., h> a - :

f<l,l> 1. f<l,2> 2.

I<2.1> 2, r<2.2> 4,

(<3A> 3. f<3.2> b.

l<4.1>-4. r<4,2>-8.

f<.., b> h:

f<l.l> И. f<J.2> I

f<2.1> И. f<2,2> И,

r<3,l> 9, f<3,2> 1.

{<4,1> e. r<4,2> И,

f S.l И. f<5,2> 1.

f<1.3> 4. f<l.i> K1.5> 6

f<2.3> 5. f<2,4> <2,5> 7

f<3,3> 6. f<3.i> 7. f<3,5> 8

f<4,3> 7. f<4.4> H. f<4.5> 9

f<5.3> 8. f<5.i> V. f<5.5) 1И

fvl.3> 1. {<1,ЛУ i. J<1,5> S t<2,3> 6, r<2,4> 8. r<2,5> 1Й l<3.3> 9. f<3.4> 12. f<3,5> IS r<4.3> 12. f<4.4> lb. r<4.5> 28

, f<4.i>tb. f<5.4) 2И. f<.,S>-2b

f<l.J> v.. f<l.4> I. f<l,5> f<2,3> 1. I<2.4> f<2,5> -3

f<3.3> . f<3.4> I. f<3.5> 2 f<4,3> 1. f<4.4> И. r<4.5> I f<5.3> 2. r<5.4> 1. r<5,5> И

Рис. 14.10. Приложение Chl4Ex04 в действии

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

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

Первым делом определяется тип делегата с именем TwoIntegerOperationDelegate для представления метода, принимающего два параметра int и возвращающего результат int:

delegate int TwoIntegerOperationDelegate(int paramA, int paramB);

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

Затем добавляется метод по имени PerformOperations (), который принимает единственный параметр типа TwoIntegerOperationDelegate:

static void PerformOperations(TwoIntegerOperationDelegate del) {

Его предназначение состоит в том, что ему можно передавать экземпляр делегата (а также анонимный метод или лямбда-выражение, поскольку эти конструкции тоже компилируются в экземпляр делегата), и он будет вызывать метод, который предоставляет этот экземпляр делегата, с рядом значений:

for (int paramAVal = 1; paramAVal <= 5; paramAVal++) {

for (int paramBVal = 1; paramBVal <= 5; paramBVal++) {

int delegateCallResult = del(paramAVal, paramBVal);

После этого осуществляется вывод параметров и результатов на консоль:

Console.WriteCf({0},{1})={2} , paramAVal, paramBVal, delegateCallResult);

if (paramBVal != 5)

Console.Write ( , );

Console.WriteLine ();



1 ... 131 132 133 [ 134 ] 135 136 137 ... 396

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