Нэш Трей - C# 2010. Ускоренный курс для профессионалов (2010) (1160865), страница 134
Текст из файла (страница 134)
Рассмотрим следующий код, в котором изменения выделены полужирным: пябпс Бузсеяы озала Ча11багогЕхгепзтопз) паяеярасе Ча11багогЕхгепзаопз ( рпЫЬс зсастс с1аяя ча11басогя ( роЫЬс яеагбс чогб Ча1гбаге( СЫз БСг1пд зСг ) ( // Что-то делать для проверки экземпляра ясгтпд. Сопзо1е.иг1сеЫпе( "Экземпляр Ясгтпо с 1"" + зсг ч "1" проверен." ); ) роЫЬс зсвсяс чо1б ча1гбасе( сь1я еар1оуее етр ) ( // Что-то делать для проверки экземпляра Еир1оуее. 500 Глаза! 4 Сопяо1е.нгтге11пе( "** Сбой при проверке экземпляра Евр1оуее! **" ); ) роь11с асасас чо1б ча11с(асе<т>( сь1з т оьб ) мазке Т: 1Ча11даеог ( оЬБ . ПоЧа11баеьоп (); Сопао1е.иг1ееьвпе( "Проверен экземпляр следуаа(его" + " типа: " + оЬ5.6еетура() ) ) ) роЬ11с Таеегтасе 1Ча1ы)аеог ( чо1б воча11оас1оп() ) ) рпЬ11с с1аяя Бпрр1уСаЬтпеС: 1ча116аеог роЬ11с чово Воча11с(ае1оп() ( Сопзо1е.кгвее1ысе( ыугдроверка Борр1усаЬ1аее" ); ) рпЬ11с с1аяя Евр1оуее ( рпЬ11с с1аяя МуАрр11сагтоп ( ягяСсс чогб Матп() ( Ясгспд баса = "некоторые важные данные"; Борр1уСаЬЕпеС япрр11ея = пен Япрр1уСаЬ1пе (); Евр1оуее Ьгьзс(у = пен Евр1оуее(); ЯаСа.уа11баСе(); зпрр11ез.Ча11баСе(); ЬгЬасу.Ча116аСе(); ) Теперь, если экземпляр, на котором вызывается ча11басе, реализует 1ча11басог, и не существует версии ча11басе.
которая принимает в точности его тнп в первом параметре, то будет вызвана обобщенная форма ча11басе, которая затем передается методу боча11бастоп на экземпляре. Обратите внимание, что расширяющий метод. первый параметр которого имел тип Яирр1уСаЬТпеС, был удален, чтобы компилятор мог выбрать обобщенную версию. Если его оставить, то код метода Матп. как он показан выше, вызовет именно его. Но даже если не удалять необобщенный расширяющий метод, то все равно можно заставить компилятор вызывать обобщенную версию, изменив синтаксис в точке вызова, как показано ниже; рсЬ11с с1азя МуАрр11сагтоп ( ягаС(с чогя Ма(п() ( БСгтпд бага = "некоторые важные данные"; Яцрр1уСаЬгпеС япрр11ея = пен Яорр1уСав(пеС() Евр1оуее Ьгьабу = пен Евр1оуее(); Оагя.уа11баге(); Расширяющие методы 501 // Прннттднвэльно ннзаавь обобяэнняв версию.
зирр11вз Ла1Ыаеесзирр1уюаььаее> (] т Ьгъэбу.уа11баге С Теперь в методе Матс компилятору предоставлено больше информации, что ограничит его поиск метода Ча11бэсе до только обобщенной формы расширяющего метода, принимающей один параметр обобщенного типа. Резюме В атой главе рассматривались расширяющие методы, включая способы их объявления и вызова, а также описание того, как компилятор реализует их "за кулисами". Вдобавок было показано, что они являются "синтаксическим сахаром", не требуя для своей работы никаких изменений исполняющей системы.
Расширяющие методы могут вызвать путаницу при неправильном применении, поэтому были рассмотрены ловушки, которых следует избегать. Было показано, как использовать эти методы при создании таких полезных вещей, как итераторы (типы 1хссюегэЬ1е<Т>) для контейнеров, которые не являются перечислимыми по умолчанию. Для типов, имеющих перечисли- тели, можно определять альтернативные перечислители, которые функционируют специальным образом. Как будет показано в главе 15, в комбинации с лямбда-выражениями расширяющие методы обеспечивают чрезвычайно полезную выразительность.
При рассмотрении способа создания пользовательских итераторов был предпринят обходной маневр (с использованием анонимных функций вместо лямбда-выражений), чтобы продемонстрировать мир функционального программирования, открытый средствами, которые были добавлены в СЗ 3.0. В случае применения лямбда-выражений вместо анонимных методов код в этих примерах становится намного яснее. Следующая главе посвящена лямбда-выражениям, которые действительно обеспечивают возможность функционального программирования на СФ в синтаксически сжатом виде.
Вдобавок они позволяют преобразовать функциональные выражения либо в код или данные в форме П кода, либо в дерево выражений. глдвд 15 Лямбда-выражения в ольшинство новых средств С№ 3.0 открывают программистам на С№ мир выразительного функционального программирования. Функциональное программирование в его чистом виде — это методология программирования, построенная на основе неизменяемых переменных (иногда называемых символами), функций, которые могут производить другие функции, и рекурсии; и это лишь несколько его основ.
К выдающимся языкам функционального программирования можно отнести 1Звр, Наз)ге11, Р№' и Всйеше'. Однако функциональное программирование не требует применения чистого функционального языка, и его с успехом можно реализовать на традиционных императивных языках, таких как все С-подобные языки (включая С№).
Средства, добавленные в С№ 3.0, трансформируют язык в более выразительный гибридный язык, в котором приемы императивного и функционального программирования сосуществуют в гармонии друг с другом. Лямбда-выражения — несомненно. самый большой кусок этого пирога функционального программирования. Введение в лямбда-выражения Лямбда-выражения позволяют кратко определять функциональные объекты для использования в любой момент. В языке С№ эта возможность всегда поддерживалась через делегаты, с помощью которых можно создать функциональный объект (в форме делегата) и привязать к нему код обратного вызова во время создания.
Лямбда-выражения связывают зти два действия — создание и подключение — в один выразительный оператор кода. Вдобавок с функциональными объектами легко ассоциировать окружение, используя конструкцию под названием замыкание (с!овпге). Функционал ((ипсцопэ))— это функция, принимающая функции в своем списке параметров и оперирующая этими функциями, возможно, даже возвращая другую функцию в результате. Например, функционал может принимать две функции, одна из которых выполняет одну математическую операцию, а другая — другую математическую операцию, и возвращать третью функцию, представляющую собой комбинацию первых двух. Лямбда-выражения предлагают более естественный способ создания и вызова функционалов.
' Р№ — замечательный новый язык функционального программирования для .МЕТ Ргагпежог1г. Подробную информацию о нем можно получить в книге Роберта Пикеринга (йоЬег! Р!сяег!пд) УЬигк1аяопв оГ" РВ (Аргевв, 2007 г). Те, кто знаком с метапрогрвммарозанием на Се и определенно знакомы и с приемами функционального программирования. Есзи вы используете С++ и интересуетесь метапрограммированием, почитайте блестки!ую юппу Дэвида Абрвхзмса (Ватгб АЬгайаглз) и Алексея ?Уртового (А1е1гвеу Оигточоу) С++ Те пр1ате Меыргодгатптз!д (Або!зоп-цГез!еу Рго(евв!опа1. 2004 г ).
504 Г ва!5 В простых синтаксических терминах лямбда-выражеиие — это синтаксис, посредством которого можно объявлять анонимные функции (делегаты( более гладким и выразительиым образом. В то же время, как будет показано далее, их возможности иамиого более многогранны. Практически каждое использоваиие анонимного метода может быть эамеиеио лямбда-выражеиием.
Вообще говоря, иет причин, по которым нельзя внедрить технику функционального программирования в С№ 2.0'. Однако синтаксис лямбда-выражеиий может потребовать некоторого времени иа привыкание. С другой стороны, синтаксис лямбда-выражеиий очень прямолинеен. Тем ие менее, встроенные в код лямбда-выражеиия иногда ие совсем просто расшифровать.
Лямбда-выражеиия принимают две формы. Форма, которая является наиболее прямой заменой анонимных методов по сиитексису, представляет собой блок кода, заключеииый в фигурные скобки. Эту форму лямбда-выражеиия иногда называют лямбдаопералюром. Оиа является прямой заменой анонимных методов. Лямбда-выражеиия, с другой стороны, предлагают еще более краткий способ объявления анонимного метода и ие требуют ии кода в фигурных скобках, ии оператора возврата. Оба типа лямбда-выражеиий могут быть преобразованы в делегаты.
Однако лямбда-выражеиия без блоков операторов представляют собой нечто действительно впечатляющее. С помощью типов из пространства имен яуяееа. Ь1пс(. Ехргеяя№опя их можно преобразовать в деревья выражений. Другими словами, функция, описанная в коде, превращается в данные. Тема создаиия деревьев выражений из лямбда-выражеиий раскрывается в разделе "Деревья выражений" далее в главе.
Лямбда-выражения и замыкания Для начала рассмотрим простейшую форму лямбда-выражеиий. ие содержащую блока операторов. Как упоминалось в предыдущем разделе, лямбда-выражеиие — это сокращенный способ объявления простого анонимного метода. Следующее лямбда-выражеиие может быть использовано в качестве делегата, принимающего один параметр и возвращающего результат деления значения параметра иа 2: х => х / 2 Это выражение говорит следующее: "взять х в качестве параметра и вернуть результат следующей операции иа х".










