Категории
Самые читаемые
onlinekniga.com » Компьютеры и Интернет » Программирование » Полное руководство. С# 4.0 - Шилдт Герберт

Полное руководство. С# 4.0 - Шилдт Герберт

Читать онлайн Полное руководство. С# 4.0 - Шилдт Герберт

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 134 135 136 137 138 139 140 141 142 ... 188
Перейти на страницу:

Для выполнения запроса в данном примере программы организуется следующийцикл.foreach(int i in posNums) Console.WriteLine(i + " ");

В этом цикле переменная posNums указывается в качестве коллекции, к которойпроисходит обращение на каждом шаге цикла. В цикле foreach соблюдаются правила, определенные в запросе и доступные по ссылке из переменной posNums. На каждом шаге цикла возвращается очередной элемент, полученный из массива. Этот процесс завершается, когда запрашиваемых элементов в массиве больше не обнаружено.В данном примере тип int переменной шага цикла i указывается явно, поскольку позапросу извлекаются элементы именно этого типа. Явное указание типа переменнойшага цикла вполне допустимо в тех случаях, когда заранее известен тип значения, выбираемого по запросу. Но в более сложных случаях оказывается проще, а иногда даженужно, указывать тип переменной шага цикла неявным образом с помощью ключевого слова var.Неоднократное выполнение запросов

Итак, в запросе определяются правила, по которым извлекаются данные, но этогоявно недостаточно для получения результатов, поскольку запрос должен быть выполнен, причем это может быть сделано несколько раз. Если же в промежутке между последовательно производимыми попытками выполнить один и тот же запрос источникданных изменяется, то получаемые результаты могут отличаться. Поэтому как толькозапрос определен, его выполнение будет всегда давать только самые последние результаты. Обратимся к конкретному примеру. Ниже приведен другой вариант рассматриваемой здесь программы, где содержимое массива nums изменяется в промежуткемежду двумя последовательно производимыми попытками выполнить один и тот жезапрос, хранящийся в переменной posNums.// Сформировать простой запрос.using System;using System.Linq;using System.Collections.Generic;class SimpQuery { static void Main() { int[] nums = { 1, -2, 3, 0, -4, 5 }; // Сформировать простой запрос на получение только положительных значений. var posNums = from n in nums where n > 0 select n; Console.Write("Положительные значения из массива nums: "); // Выполнить запрос и отобразить его результаты. foreach(int i in posNums) Console.Write(i + " "); Console.WriteLine(); // Внести изменения в массив nums. Console.WriteLine("nЗадать значение 99 для элемента массива nums[1]."); nums[1] = 99; Consofe.Write("Положительные значения из массива numsn" + "после изменений в нем: "); // Выполнить запрос второй раз. foreach(int i in posNums) Console.Write(i + " "); Console.WriteLine(); }}

Вот к какому результату приводит выполнение этой программы.Положительные значения из массива nums: 1 3 5Задать значение 99 для элемента массива nums[l].Положительные значения из массива numsпосле изменений в нем: 1 99 3 5

Как следует из результата выполнения приведенной выше программы, значениеэлемента массива nums[1] изменилось с -2 на 99, что и отражают результаты повторного выполнения запроса. Этот важный момент следует подчеркнуть особо. Каждаяпопытка выполнить запрос приносит свои результаты, получаемые при перечислениитекущего содержимого источника данных. Поэтому если источник данных претерпевает изменения, то могут измениться и результаты выполнения запроса. Преимуществатакого подхода к обработке запросов весьма значительны. Так, если по запросу получается список необработанных заказов в Интернет-магазине, то при каждой попыткевыполнить запрос желательно получить сведения обо всех заказах, включая и толькочто введенные.Связь между типами данных в запросе

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

Тип переменной диапазона должен соответствовать типу элементов, хранящихся в источнике данных. Следовательно, тип переменной диапазона зависит от типаисточника данных. Как правило, тип переменной диапазона может быть выведенсредствами С#. Но выводимость типов может быть осуществлена при условии, чтов источнике данных реализована форма интерфейса IEnumerable, где Т обозначает тип элементов в источнике данных. (Как упоминалось выше, форма интерфейсаIEnumerable реализуется во всех массивах, как, впрочем, и во многих других источниках данных.) Но если в источнике данных реализован необобщенный вариантинтерфейса IEnumerable, то тип переменной диапазона придется указывать явно.И это делается в операторе from. Ниже приведен пример явного объявления типаint переменной диапазона n.var posNums = from int n in nums // ...

Очевидно, что явное указание типа здесь не требуется, поскольку все массивы неявно преобразуются в форму интерфейса IEnumerable, которая позволяет вывеститип переменной диапазона.

Тип объекта, возвращаемого по запросу, представляет собой экземпляр интерфейса IEnumerable, где Т — тип получаемых элементов. Следовательно, тип переменной запроса должен быть экземпляром интерфейса IEnumerable, а значениеТ должно определяться типом значения, указываемым в операторе select. В предыдущих примерах значению Т соответствовал тип int, поскольку переменная п имелатип int. (Как пояснялось выше, переменная n относится к типу int, потому что элементы именно этого типа хранятся в массиве nums.) С учетом явного указания типаIEnumerable упомянутый выше запрос можно было бы составить следующимобразом.IEnumerable<int> posNums = from n in nums where n > 0 select n;

Следует иметь в виду, что тип элемента, выбираемого оператором select, долженсоответствовать типу аргумента, передаваемого форме интерфейса IEnumerable,используемой для объявления переменной запроса. Зачастую при объявлении переменных запроса используется ключевое слово var вместо явного указания ее типа,поскольку это дает компилятору возможность самому вывести соответствующий типданной переменной из оператора select. Как будет показано далее в этой главе, такой подход оказывается особенно удобным в тех случаях, когда оператор select возвращает из источника данных нечто более существенное, чем отдельный элемент.Когда запрос выполняется в цикле foreach, тип переменной шага цикла долженбыть таким же, как и тип переменной диапазона. В предыдущих примерах тип этойпеременной указывался явно как int. Но имеется и другая возможность: предоставитькомпилятору самому вывести тип данной переменной, и для этого достаточно указатьее тип как var. Как будет показано далее в этой главе, ключевое слово var приходитсяиспользовать и в тех случаях, когда тип данных просто неизвестен.Общая форма запроса

У всех запросов имеется общая форма, основывающаяся на ряде приведенных нижеконтекстно-зависимых ключевых слов.Ascendingbydescendingequalsfromgroupinintojoinletonorderbyselectwhere

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

Запрос должен начинаться с ключевого слова from и оканчиваться ключевым словом select или group. Оператор select определяет тип значения, перечисляемогопо запросу, а оператор group возвращает данные группами, причем каждая группаможет перечисляться по отдельности. Как следует из приведенных выше примеров,в операторе where указываются критерии, которым должен удовлетворять искомыйэлемент, чтобы быть полученным по запросу. А остальные операторы позволяют уточнить запрос. Все они рассматриваются далее по порядку.Отбор запрашиваемых значений с помощью оператора where

Как пояснялось выше, оператор where служит для отбора данных, возвращаемыхпо запросу. В предыдущих примерах этот оператор был продемонстрирован в своейпростейшей форме, в которой для отбора данных используется единственное условие. Однако для более тщательного отбора данных можно задать несколько условийи, в частности, в нескольких операторах where. В качестве примера рассмотрим следующую программу, в которой из массива выводятся только те значения, которые положительны и меньше 10.// Использовать несколько операторов where.using System;using System.Linq;class TwoWheres { static void Main() { int[] nums = { 1, -2, 3, -3, 0, -8, 12, 19, 6, 9, 10 }; // Сформировать запрос на получение положительных значений меньше 10. var posNums = from n in nums where n > 0 where n < 10 select n; Console.Write("Положительные значения меньше 10: "); // Выполнить запрос и вывести его результаты. foreach(int i in posNums) Console.Write (i + " "); Console.WriteLine(); }}

1 ... 134 135 136 137 138 139 140 141 142 ... 188
Перейти на страницу:
На этой странице вы можете бесплатно читать книгу Полное руководство. С# 4.0 - Шилдт Герберт.
Комментарии