Нэш Трей - C# 2010. Ускоренный курс для профессионалов (2010) (1160865), страница 141
Текст из файла (страница 141)
В этой главе внимание будет сосредоточено на ЫНЯ го ОЬ)есгз, поскольку эта реализация позволяет получать сообщения ЫНЯ напрямую, не включая каких-либо дополнительных уровней и технологий. На заметку! Разработка Ь!НО началась некоторое время назад в М!сгозой, и своим появлением эта технология обязана Андерсу Хейлсбергу (Апбегз Не)(зоегб) и Питеру Голду (Ре(ег Во)б).
Идея состояла в создании более естественного и интегрированного способа доступа к данным из языка, подобного С». Однако в то же время было нежелательно реализовывать его таким способом, который бы дестабилизировал работу компилятора С» и привносил путаницу в язык. Поэтому появился смысл добавить в С» ряд строительных блоков, которые бы обеспечили функциональность и выразительность ОНО, Отсюда и появились такие средства, как лямбда-выражения, анонимные типы, расширяющие методы и неявно типизированные переменные.
Все они — не только великолепные средства сами по себе, но еще и служат основой для ВНО, Язык 1.ПчЯ очень хорошо справляется со своим предназначением, позволяя программистам сосредоточиться на бизнес-логике и меньше тратить времени на кодирование рутинных деталей, которые обычно сопровождают написание кода доступа к данным.
Если вы ранее занимались построением приложений, работающих с данными, вспомните, насколько часто приходилось снова и снова писать один и тот же код с небольшими вариациями. Язык Ы(ч'Я избавляет от этого. ' За более исчерпывающим описанием ЫХЯ обращайтесь в книгу Джозефа Раттца-мл. ЬОУЯ: язык инлмгрирсванньгх запросов в С№ 2008 для профессионалов (ИД "Вильямс", 2008 г]. 62п Глава ) б Мост к данным На протяжении книги неоднократно подчеркивалось, что почти все новые средства, введенные в С№ З.О, стимулируют применение модели функционального программирования. На то имеется веская причина, потому что запросы данных — обычно функциональный процесс. Например, оператор ВЯЬ сообщает серверу в точности то, что нужно сделать.
Он не описывает объектов и структур, а также динамических и статических отношений между ними, т.е. всего того, чем приходится заниматься во время проектирования нового приложения на объектно-ориентированном языке. Таким образом, функциональное программирование играет ключевую роль. и здесь применимы любые приемы, знакомые по таким функциональным языкам программирования, как Ызр, Всйегпе или г №.
Выражения запросов На первый взгляд, выражения запросов ЫХЯ выглядят очень похоже на выражения в языке ВЯЬ. Но не допускайте ошибку; Ы)т)Я вЂ” это не ЭЯЬ. Прежде всего, Ы))(Я строго типизирован. В конце концов, С№ — строго типизированный язык. поэтому то же касается и ЫНЯ. Для построения выражений запросов в язык было добавлено несколько новых ключевых слов.
С точки зрения компилятора реализация выражений запросов предельно проста. Выражения запросов Ы)чЯ обычно транслируются в цепочки вызовов расширяющих методов на последовательности или коллекции. Этот набор расширяющих методов четко определен и носит название сгпандарптных операций запросоа.
На заметку) Модель ВНО полностью расширяема. Если компилятор просто транслирует выражения запросов в последовательности вызовов расширяющих методов, из этого следует, что можно предоставить собственные реализации этих расширяющих методов. На самом деле так оно и есть. Например, класс Бузсеп. ьгпц. епппегаЬ1е предоставляет реализации этих методов для ВНО то ОЬ)ес(з, в то время как БузСеп.
Ь1пг(. Осе гуаЬ1е предлагает реализации этих методов для опроса типов, реализующих интерфейс 1 О ое гуаЬ1е<т>, которые часто используются с ВНО (о ЕОЬ. Давайте посмотрим, как выглядят запросы. В следующем примере создается коллекция объектов Епр1оуее, а затем выполняется простой запрос: цз1по Бузсеп; пасло Бузсеп.шпг(; цзгпо Бузгеп.со11есг1опз.оепегсс; рсЬ11с с1аэв Епр1оуее ( рнЫгс згг1по Гггзгквпе ( 9егг зеС; рыЫ1с эгг1по Оазгиапе ( оеС; зегг ) роЫгс Оесгпз1 Ба1агу ( оегг зеС; ) рсЬ11с ОаСеТгпе БСагСОзге ( деС, "зеС; ) риЬ11с с1азз Бспр1ериегу ( агат>с тосб Нага() // Оседать базу данных сотрудников.
тат еэр1оуеез = пен 11зс<Епр1оуее> ( пен Епр1оуее ( Г1гэснапе = тасе", Оазгквпе = "ВоЬ", Ба1агу = 94000, ВНО: язык интегрированных запросов 527 5СагСоэСе = оакеТ1пе.Рэгзе("1/4/1992") пен Евр1оуее ( РЬгзткапе = ",)апе", Ьаэккапе = "рое", Ва1агу = 123000, Всзгсовсе = оасетспе.Рагэе("4/12/1998") ), пен Евр1оуее ( Ругзгкаве = "М11Соп", Ьззккаве = "Иэг(г(апэ", 5а1агу = 1000000, ВСаггоаСе = оагеТЬве.Расее("12/3/1969") ): таг т)вегу ю Евою еюр1оуее гп еюр1оуеез ивеге евгр1оуее.аа1агу > 100000 огг(егву еюр1оуее.Ьаеекюзе, евр1оуее.в'1гаекапе ее1еок пеи ( Ьазекаюе = еюр1оуее.ьавенюве, Рт.геенаюе м еаат1оуее.У1геекаюв )) Сопзо1е.нгЬСеЬгое( "Высокооплачиваемые сотрудники:" ); Тогеасп( чаг Ьсев 1п Чиегу ) ! Сопзо1е.нгсгеЬЬпе( "(О), (1)", 1геп.Ьээгиаве, ЬСев.гсгзгкапе ); Прежде всего, понадобится импортировать пространство имен Вуэгеп.
Ь1пг(, как будет показано в разделе "Стандартные операции запросов" далее в главе. В приведенном примере выражение запроса выделено полужирным. На первый взгляд выражение Ы)т)Я может показаться довольно необычным. С другой стороны, язык СВ происходит от С++ и дата, а синтаксис ЫР(Я совсем не похож на эти языки. На заметку! Те, кто знаком с ЕОЬ, скорее всего, сразу отметят, что этот запрос напоминает вам нечто хорошо известное. В ЯОЬ конструкция зе1есс обычно стоит в начале выражения. Существует несколько причин того, что в СВ имеет смысл обратное. Одна из них — облегчение работы (псейзепзе. Если бы в рассмотренном примере конструкция эе1есС стояла в начале, для средства (п!ейзепзе было бы сложнее определить свойства, имеющиеся у епр1оуее, поскольку тип епр1оуее на тот момент был бы не известен.
Перед выражением запроса создается простой список экземпляров Евр1оуее, чтобы предоставить данные для работы. Каждое выражение запроса начинается с конструкции стоп, объявляющей то, что называется переменной диапазона. Конструкция стоп в рассматриваемом примере очень похожа на оператор согеасн в том, что осуществляет итерацию по коллекции евр1оуеез, сохраняя на каждом шаге очередной элемент коллекции в переменной евр1оуее. После конструкции стоп запрос содержит последовательность конструкций, в которых можно использовать различные операции запроса для фильтрации данных, представленных переменной диапазона. В примере применяются конструкции ниеге и огс)егЬу. И, наконец, выражение закрывается операцией проекцигс Выполнение проекции в выражении запроса обычно приводит к созданию другой коллекции информации или одиночной порции информации, представляющей собой трансформированную версию коллекции, по которой выполняется итерация с помощью переменной диапазона.
В предыдущем примере в результат должны были включаться только имена и фамилии сотрудников. 528 Глава ) б Другая вещь, которую следует отметить — это использование анонимных типов в конструкции яе1есг. Запрос должен был трансформировать исходные данные в коллекцию структур, где каждый экземпляр содержит свойство Рагяспаве, свойство Ьаяснаве и ничего более.
Разумеется, можно было бы объявить такую структуру до выполнения запроса, когда конструкция яе1есг создаст экземпляры этого типа, однако, такой подход в некоторой степени нивелирует удобство и выразительность запроса ЫЧЯ. Что более важно, и об этом пойдет речь в разделе "Преимущества лени" далее в главе — выражение запроса не выполняется в точке присваивания переменной запроса. Вместо этого переменная запроса в рассматриваемом примере реализует интерфейс 1ЕппвегаЬ1е<Т>,и последующееприменение Тогеасп на переменной <(пегу производит результат. Конечный результат построения выражения запроса сосредоточен в том, что называется переменная запроси, в данном примере — это <(песу.
Обратите внимание, что используется неявно типизированная переменная. А можно ли узнать тип запроса? Отправив результат вызова <[пегу. Оестуре на консоль, можно увидеть следующий тип: Буясев.шпЧ.ЕппвегаЬ1е+<яе1есс1сегасог>б Ь 2[Евр1оуее, <>Т Нпопувопятурео'2[Буясев.япг1пя,зуясев.зсггпд]) Вернемся к расширяющим методам и лямбда-выражениям Прежде чем приступить к более подробному разбору элементов выражения Ы[([й, рассмотрим альтернативный способ выполнения той же работы. Фактически, это приблизительно то, что делает компилятор "эа кулисами". Синтаксис Ы[ЧЯ выглядит очень чуждым в преимущественно императивном языке.
каковым является С№. Легко прийти к заключению, что язык С№ претерпел существенные модификации для реализации ЫХЯ. В действительности компилятор просто трансформирует выражение ЫХЯ в последовательность вызовов расширяющих методов, которые принимают лямбда-выражения. В пространстве имен Яуясев. Ьапц есть два интересных статических класса, буквально переполненные расширяющими методами — ЕппвегаЬ1е и ОпэгуаЬ1е. Класс ЕппвегэЬ1е определяет коллекцию обобщенных расширяющих методов, полезных для типов 1ЕппвегаЬ1е, тогда как ОпегуаЬ1е определяет ту же коллекцию обобщенных расширяющих методов, но применимых к типам 1ОпегуэЬ1е. Имена этих расширяющих методов совпадают с конструкциями выражений запросов.
Это не случайно, поскольку расширяющие методы реализуют стандартные операции запросов, которые упоминались в предыдущем разделе. В действительности выражение запроса из предыдущего примера может быть заменено следующим кодом: наг Чпегу = евр1оуеея .Хпеге( евр => евр.за1эгу > 100000 ) .Огпегву( евр => евр.ьяягнаве .Огс[е<Ву( евр => евр.Е1гяскаве ) .Бе1есс( евр => пеэ (Ьаяскэве = евр.ьзяснаве, Еьгяснаве = евр.г1гяснаве) ); Обратите внимание, что это просто цепочка вызовов расширяющих методов на интерфейсе 1ЕппвегаЬ1е, который реализован ел1р1оуеея.
Фактически, можно пойти на шаг дальше и изменить оператор внутри, исключив синтаксис расширенных методов и просто вызывая их как статические методы: гаг Чпегу = ЕппвегаЪ1е.ае1есс ( ЕпивегаЬ1е.огяегВу( ЕповегаЬ|е.огс)егВу( НМ0: язык интегрированных запросов 529 ЕпцветаЬ1е.кпеге( евр1оуеея, евр => евр.зя1ату > 100000), евр => евр.Ьзятыаве ), евр => евр.ГЬтятыаве ), евр => пен (Ьаятняве = евр.Ьзятыяве, Г1гятызве = евр.ГЬгягыяве) ); Но зачем подобное может понадобитьсяг Это просто показано для иллюстрации того,что в действительности происходит "за кулисами".Истинные приверженцы анонимных методов С№ 2.0 может продвинуться еще дальше и заменить лямбда-выражения анонимными методами.











