Чтение онлайн

на главную - закладки

Жанры

Полное руководство. С# 4.0
Шрифт:

Вот к какому результату приводит выполнение этой программы. Использование лямбда-выражения 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? Ответить на этот вопрос можно так: компиля тор делает заключение о типе параметра и типе результата вычисления выражения по типу делегата. Следовательно, параметры и возвращаемое значение лямбда- выражения должны быть совместимы по типу с параметрами и возвращаемым зна чением делегата.

Несмотря на всю полезность логического заключения о типе данных, в некоторых случаях приходится явно указывать тип параметра лямбда-выражения. Для этого до статочно ввести конкретное название типа данных. В качестве примера ниже приведен другой способ объявления экземпляра делегата incr. Incr incr = (int count) => count + 2;

Как видите, count теперь явно объявлен как параметр типа int. Обратите также внимание на использование скобок. Теперь они необходимы. (Скобки могут быть опу щены только в том случае, если задается лишь один параметр, а его тип явно не ука зывается.)

В предыдущем примере в обоих лямбда-выражениях использовался единственный параметр, но в целом у лямбда-выражений может быть любое количество параметров, в том числе и нулевое. Если в лямбда-выражении используется несколько параметров, их необходимо заключить в скобки. Ниже приведен пример использования лямбда- выражения с целью определить, находится ли значение в заданных пределах. (low, high, val) => val >= low && val <= high;

А вот как объявляется тип делегата, совместимого с этим лямбда-выражением. delegate bool InRange(int lower, int upper, int v);

Следовательно, экземпляр делегата InRange может быть создан следующим об разом. InRange rangeOK = (low, high, val) => val >= low && val <= high;

После этого одиночное лямбда-выражение может быть выполнено так, как показа но ниже. if(rangeOK(1, 5, 3)) Console.WriteLine( "Число 3 находится в пределах от 1 до 5.");

И последнее замечание: внешние переменные могут использоваться и захватывать ся в лямбда-выражениях таким же образом, как и в анонимных методах. Блочные лямбда-выражения

Как упоминалось выше, существуют две разновидности лямбда-выражений. Первая из них, одиночное лямбда-выражение, была рассмотрена в предыдущем разделе. Тело такого лямбда-выражения состоит только из одного выражения. Второй разновидно стью является блочное лямбда-выражение. Для такого лямбда-выражения характерны расширенные возможности выполнения различных операций, поскольку в его теле до пускается указывать несколько операторов. Например, в блочном лямбда-выражении можно использовать циклы и условные операторы if, объявлять переменные и т.д. Создать блочное лямбда-выражение нетрудно. Для этого достаточно заключить тело выражения в фигурные скобки. Помимо возможности использовать несколько опера торов, в остальном блочное лямбда-выражение, практически ничем не отличается

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

Ниже приведен пример использования блочного лямбда-выражения для вычисле ния и возврата факториала целого значения. // Продемонстрировать применение блочного лямбда-выражения. using System; // Делегат IntOp принимает один аргумент типа int // и возвращает результат типа int. delegate int IntOp(int end); class StatementLambdaDemo { static void Main { // Блочное лямбда-выражение возвращает факториал // передаваемого ему значения. IntOp fact = n => { int r = 1; for(int i=1; i <= n; i++) r = i * r; return r; }; Console.WriteLine("Факториал 3 равен " + fact(3)); Console.WriteLine("Факториал 5 равен " + fact(5)); } }

При выполнении этого кода получается следующий результат. Факториал 3 равен 6 Факториал 5 равен 120

В приведенном выше примере обратите внимание на то, что в теле блочного лямбда-выражения объявляется переменная r, организуется цикл for и используется оператор return. Все эти элементы вполне допустимы в блочном лямбда-выражении. И в этом отношении оно очень похоже на анонимный метод. Следовательно, многие анонимные методы могут быть преобразованы в блочные лямбда-выражения при обновлении унаследованного кода. И еще одно замечание: когда в блочном лямбда- выражении встречается оператор return, он просто обусловливает возврат из лямбда- выражения, но не возврат из охватывающего метода.

И в заключение рассмотрим еще один пример, демонстрирующий блочное лямбда- выражение в действии. Ниже приведен вариант первого примера из этой главы, изме ненного с целью использовать блочные лямбда-выражения вместо автономных мето дов для выполнения различных операций со строками. // Первый пример применения делегатов, переделанный с // целью использовать блочные лямбда-выражения. using System; // Объявить тип делегата. delegate string StrMod(string s); class UseStatementLambdas { static void Main { // Создать делегаты, ссылающиеся на лямбда- выражения, // выполняющие различные операции с символьными строками. // Заменить пробелы дефисами. StrMod ReplaceSpaces = s => { Console.WriteLine("Замена пробелов дефисами."); return s.Replace(' ', '-'); }; // Удалить пробелы. StrMod RemoveSpaces = s => { string temp = int i; Console.WriteLine("Удаление пробелов."); for(i=0; i < s.Length; i++) if (s[i] != ' ') temp += s[i]; return temp; }; // Обратить строку. StrMod Reverse = s => { string temp = ""; int i, j; Console.WriteLine("Обращение строки."); for(j=0, i=s.Length-1; i >= 0; i--, j++) temp += s [i]; return temp; }; string str; // Обратиться к лямбда-выражениям с помощью делегатов. StrMod strOp = ReplaceSpaces; str = strOp("Это простой тест."); Console.WriteLine("Результирующая строка: " + str); Console.WriteLine; strOp = RemoveSpaces; str = strOp("Это простой тест."); Console.WriteLine("Результирующая строка: " + str); Console.WriteLine; strOp = Reverse; str = strOp("Это простой тест."); Console.WriteLine("Результирующая строка: " + str); } }

Результат выполнения кода этого примера оказывается таким же, как и в первом примере применения делегатов. Замена пробелов дефисами. Результирующая строка: Это-простой-тест. Удаление пробелов. Результирующая строка: Этопростойтест. Обращение строки. Результирующая строка: .тсет йотсорп отЭ События

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

Поделиться:
Популярные книги

Барон играет по своим правилам

Ренгач Евгений
5. Закон сильного
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Барон играет по своим правилам

Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Клеванский Кирилл Сергеевич
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.51
рейтинг книги
Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Герцогиня в ссылке

Нова Юлия
2. Магия стихий
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Герцогиня в ссылке

Ну привет, заучка...

Зайцева Мария
Любовные романы:
эро литература
короткие любовные романы
8.30
рейтинг книги
Ну привет, заучка...

На Ларэде

Кронос Александр
3. Лэрн
Фантастика:
фэнтези
героическая фантастика
стимпанк
5.00
рейтинг книги
На Ларэде

Сердце Дракона. Том 12

Клеванский Кирилл Сергеевич
12. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.29
рейтинг книги
Сердце Дракона. Том 12

Истинная поневоле, или Сирота в Академии Драконов

Найт Алекс
3. Академия Драконов, или Девушки с секретом
Любовные романы:
любовно-фантастические романы
6.37
рейтинг книги
Истинная поневоле, или Сирота в Академии Драконов

Кодекс Охотника. Книга VI

Винокуров Юрий
6. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга VI

Гардемарин Ее Величества. Инкарнация

Уленгов Юрий
1. Гардемарин ее величества
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Гардемарин Ее Величества. Инкарнация

Сама себе хозяйка

Красовская Марианна
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Сама себе хозяйка

Душелов. Том 3

Faded Emory
3. Внутренние демоны
Фантастика:
альтернативная история
аниме
фэнтези
ранобэ
хентай
5.00
рейтинг книги
Душелов. Том 3

Газлайтер. Том 10

Володин Григорий
10. История Телепата
Фантастика:
боевая фантастика
5.00
рейтинг книги
Газлайтер. Том 10

Стеллар. Заклинатель

Прокофьев Роман Юрьевич
3. Стеллар
Фантастика:
боевая фантастика
8.40
рейтинг книги
Стеллар. Заклинатель

Возвышение Меркурия. Книга 5

Кронос Александр
5. Меркурий
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 5