Г. Шилдт - С#4.0 Полное руководство (1160795), страница 123
Текст из файла (страница 123)
Прежде всего обратите внимание на применение в данном примере программы следующего оператора. озгпс Бузсеи.ъупйг 640 Часть Ь Язык С№ Для применения средств ЕПЩ в исходный текст программы следует включить пространство имен яуя Сев. Ыпц. Затем в программе объявляется массив пита типа Тпс. Все массивы в СФ неявным образом преобразуются в форму интерфейса 1ЕпивегаЬ1е<т>. Благодаря этому любой массив в СЕ может служить в качестве источника данных, извлекаемых по запросу 1.1МЗ. Далее обьявляется запрос, по которому из массива пива извлекаются элементы только с положительными значениями.
чае рояковя = Гсов и ьи иивя ыиеге и > О яе1есг и; Переменная рояыивя называется переменной запроса. В ней хранится ссылка на ряд правил, определяемых в запросе. Обратите внимание на применение ключевого слова оаг для объявления переменной рояьзивя неявным образом. Как вам должно быть уже извеспю, благодаря этому переменная роянивя становится неявно типизированной. Такими переменными удобно пользоваться в запросах, хотя их тип можно объявить и явным образом (это должна быть одна из форм интерфейса 1ЕиивегаЬ1е<т>).
Объявляемой переменной рояьзивя в итоге присваивается выражение запроса. Все запросы начинаются с оператора гсов, определяющего два элемента. Первым из них является переменная диапазона, принимающая элементы из источника данных. В рассматриваемом здесь примере эту роль выполняет переменная и. Вторым элементом является источник данных (в данном случае — массив пита). Тип переменной диапазона выводится из источника данных.
Поэтому переменная и относится к типу 1иг. Ниже приведена общая форма оператора гсов. Гсов переменная днаиаяона ьи нсточннн данных Далее следует оператор ыЛеге, обозначающий условие, которому должен удовлетворять элемент в источнике данных, чтобы его можно было получить по запросу. Ниже приведена общая форма синтаксиса оператора ыпеге. ниеге Оулеяо выражение В этой форме оулево выражение должно давать результат типа Ьоо1.
Такое выражение иначе называется преоикатом. В запросе можно указывать несколько операторов ыпеге. В данном примере программы используется следующий оператор ыЛеге. ниеге п > О Этот оператор будет давать истинный результат только для тех элементов массива, значения которых оказываются больше нуля.
Выражение и > О будет вычисляться для каждого из п элементов массива и при выполнении запроса. В итоге будут получены только те значения, которые удовлетворяют этому условию. Иными словами, оператор ы пете выполняет роль своеобразного фильтра, отбирая лишь определенные элементы. Все запросы оканчиваются оператором яе1есс или дгоир. В данном примере используется оператор яе1есс, точно определяющий, что именно должно быть получено по запросу. В таких простых примерах запросов, как рассматриваемый здесь, выбирается конкретное значение диапазона. Поэтому по данному запросу возвращаются только те целые значения, которые удовлетворяют условию, указанному в операторе ыпеге.
В более сложных запросах можно дополнительно уточнять, что именно Глава 19. 0нО 641 следует выбирать. Например, по запросу списка рассылки может быть получена лишь фамилия адресата вместо его полного адреса. Обратите внимание на то, что оператор эе1есг завершается точкой с запятой, поскольку это последний оператор в запросе. А другие его операторы не оканчиваются точкой с запятой. Итак, переменная запроса роэнпмз создана, но результаты запроса пока еще не получены.
Дело в том, что сам запрос определяет лишь ряд конкретных правил, а результаты будут только после выполнения запроса. Кроме того, один и тот же запрос может быть выполнен два раза или больше, причем с разными результатами, если в промежутке между последовательно производимыми попытками выполнить один и тот же запрос изменяется базовый источник данных. Поэтому одного лишь объявления переменной запроса ро энпгпэ совершенно недостаточно для того, чтобы она содержала результаты запроса. Для выполнения запроса в данном примере программы организуется следующий цикл. Гьтеась(1пс х тп роэнпээ) Сопэо1е.иггссъ1пе(1 В этом циклепеременная роэнпп)э указывается в качестве коллекции, к которой происходит обращение на каждом шаге цикла. В цикле 1огеас)) соблюдаются правила, определенные в запросе и доступные по ссылке из переменной роэнпыэ.
На каждом шаге цикла возвращается очередной элемент, полученный из массива. Зтот процесс завершается, когда запрашиваемых элементов в массиве больше не обнаружено. В данном примере тип 1пс переменной шага цикла 1 указывается явно, поскольку по запросу извлекаются элементы именно этого типа. Явное указание типа переменной шага цикла вполне допустимо в тех случаях, когда заранее известен тип значения, выбираемого по запросу. Но в более сложных случаях оказывается проще, а иногда даже нужно, указывать тип переменной шага цикла неявным образом с помощью ключевого слова узг. Неоднократное выполнение запросов Итак, в запросе определяются пра4)ла, по которым извлекаются данные, но этого явно недостаточно для получения результатов, поскольку запрос должен быть выполнен, причем это может быть сделано несколько раз.
Если же в промежутке между последовательно производимыми попьпками выполнить один и тот же запрос источник данных изменяется, то получаемые результаты могут отличаться. Поэтому как только запрос определен, его выполнение будет всегда давать только самые последние результаты. Обратимся к конкретному примеру. Ниже приведен другой вариант рассматриваемой здесь программы, где содержимое массива ппп)э изменяется в промежутке между двумя последовательно производимыми попытками выполни~ь один и тот же запрос, хранящийся в переменной роэыпмэ.
// Сформировать простой запрос. пэ1пп Буэсепи иэьпд Зуэгев.Ь1пьи пэ1пп зуэгеи.со11есс1опэ.оепег1с) с1аээ 51прЦпегу ( эгаг1с то1п Махп() ( 1пс(] пппэ=(1, -2, 3, О, -4, 5)) 642 Часть!. язык С№ уу Сформировать простой запрос на получение только положительных значений. чаг рояншяя = Ггои и ьп пшпя идете и > 0 яе1еся и; Сопво1е.игьге("Положительные значения из массива пшпя: ") // Выполнить запрос и отобразить его результаты. гогеасл(1по 1 ьп рояншпв) Сопяо1е.Хгтпе(1 + " "); сопяо1е.хггсеглпе()т УУ Внести изменения в массив поия. Сопяо1е.нг1оеьгпе("~пэадать значение 99 длл элемента массива пшля(1].") пшяя(1) = 99; Сопяо1е.нг1ге("Положительные значения из массива папам" "после изменений в нем: "); Выполнить запрос второй раз.
Гогеасл(ьпп 1 1п рояншяя) Сопяо1е.истое(г + " "); Сопяо1е.нггсеььпе(); ) ) Вот к какому результату приводит выполнение этой программы. Положительные значения из массива поля: 1 3 5 Задать значение 99 длн элемента массива пома(1). Положительные значения из массива поэз после изменений в нем: 1 99 3 5 Как следует из результата выполнения приведенной выше программы, значение элемента массива пиптя [1) изменилось с -2 на 99, что и отражают результаты повторного выполнения запроса. Этот важный момент следует подчеркнуть особо. Каждая попытка выполнить запрос приносит свои результаты, получаемые при перечислении текущего содержимого источника данных.
Поэтому если источник данных претерпевает изменения, то могут измениться и результаты выполнения запроса. Преимущества такого подхода к обработке запросов весьма значительны. Так, если по запросу получается список необработанных заказов в Интернет-магазине, то при каждой попытке выполнить запрос желательно получить сведения обо всех заказах, включая и только что введенные. Связь между типами данных в запросе Как показывает предыдущий пример, запрос включает в себя переменные, типы которых связаны друг с другом. К их числу относятся переменная запрбса, переменная ' диапазона и источник данных.
Соблюсти соответствие этих типов данных очень важно, но в то же время нелегко — по крайней мере, так кажется на первый взгляд, поэтому данный вопрос заслуживает более пристального внимания. Глава 19. Ойо 643 Тип переменной диапазона должен соответствовать типу элементов, хранящихся в источнике данных. Следовательно, тип переменной диапазона зависит от типа источника данных. Как правило, тип переменной диапазона может быть выведен средствами СФ. Но выводимость типов может быть осуществлена при условии, что в источнике данных реализована форма интерфейса 1ЕппппегаЬ1е<Т>, где Т обозначает тип элементов в источнике данных. (Как упоминалось выше, форма интерфейса 1ЕпшпегаЬ1е<Т> реализуется во всех массивах, как, впрочем, и во многих других источниках данных.) Но если в источнике данных реализован необобщенный вариант интерфейса 1ЕпиппегаЬ1е, то тип переменной диапазона придется указывать явно.
И это делается в операторе Ггоьь Ниже приведен пример явного объявления типа Тпг переменной диапазона п. час рсяэпия = Ггспп ьпг и 1п пива О Очевидно, что явное указание типа здесь не требуется, поскольку все массивы неявно преобразуются в форму интерфейса 1ЕпиппегаЬ1е<Т>, которая позволяет вывести тип переменнои диапазона. Тип объекта, возвращаемого по запросу, представляет собой экземпляр интерфейса 1ЕпиппегаЬ1е<Т>, где Т вЂ” тип получаемых элементов. Следовательно, тип переменной запроса должен быть экземпляром интерфейса 1ЕппппегаЬ1е<Т>, а значение Т должно определяться типом значения, указываемым в операторе яе1есг.
В предыдущих примерах значению т соответствовал тип 1пг, поскольку переменная и имела тип ьпс. (Как пояснялось выше, переменная и относится к типу 1пг, потому что элементы именно этого типа хранятся в массиве пиия.) С учетом явного указания типа 1еппппегаЬ1е<1пг> упомянутый выше запрос можно было бы составить следующим образом. 1ЕппяегаЫе<1иг> рояэиппя = Ггст п пп ииппя яьеге п > О яе1есг п," Следует иметь в виду, что тип элемента, выбираемого оператором яе1есг, должен соответствовать типу аргумента, передаваемого форме интерфейса 1Еппппе гаЬ1е<Т >, используемой для объявления переменной запроса. Зачастую при объявлении переменных запроса используется ключевое слово час вместо явного указания ее типа, поскольку это дает компилятору возможность самому вывести соответствующий тип данной переменной из оператора яе1есг.
Как будет показано далее в этой главе, такой подход оказывается особенно удобным в тех случаях, когда оператор яе1есг возвращает из источника данных нечто более существенное, чем отдельный элемент. Когда запрос выполняется в цикле ТогеасЬ, тип переменной шага цикла должен быть таким же, как и тип переменной диапазона. В предыдущих примерах тип этой переменной указывался явно как 1пг.