На головну

Checked и unchecked 14 страница

  1. 1 страница
  2. 1 страница
  3. 1 страница
  4. 1 страница
  5. 1 страница
  6. 1 страница
  7. 1 страница

В примере

using System;

delegate void D();

class Test
{
static D[] F() {
D[] result = new D[3];
for (int i = 0; i < 3; i++) {
int x = i * 2 + 1;
result[i] = () => { Console.WriteLine(x); };
}
return result;
}

static void Main() {
foreach (D d in F()) d();
}
}

получается вывод

1
3
5

Однако при переносе объявления x за пределы цикла:

static D[] F() {
D[] result = new D[3];
int x;
for (int i = 0; i < 3; i++) {
x = i * 2 + 1;
result[i] = () => { Console.WriteLine(x); };
}
return result;
}

вывод имеет вид

5
5
5

Если в цикле for объявляется переменная итерации, то сама эта переменная считается объявленной за пределами цикла. Таким образом, если изменить пример, чтобы захватывать саму переменную итерации

static D[] F() {
D[] result = new D[3];
for (int i = 0; i < 3; i++) {
result[i] = () => { Console.WriteLine(i); };
}
return result;
}

то будет захвачен только один экземпляр переменной итерации. В этом случае вывод имеет вид

3
3
3

Делегаты анонимных функций могут иметь некоторые общие захваченные переменные и в то же время иметь отдельные экземпляры других переменных. Например, если F изменить на

static D[] F() {
D[] result = new D[3];
int x = 0;
for (int i = 0; i < 3; i++) {
int y = 0;
result[i] = () => { Console.WriteLine("{0} {1}", ++x, ++y); };
}
return result;
}

то три делегата будут захватывать один экземпляр x, но разные экземпляры y. Вывод будет иметь вид:

1 1
2 1
3 1

Отдельные анонимные функции могут захватывать один экземпляр внешней переменной. В данном примере:

using System;

delegate void Setter(int value);

delegate int Getter();

class Test
{
static void Main() {
int x = 0;
Setter s = (int value) => { x = value; };
Getter g = () => { return x; };
s(5);
Console.WriteLine(g());
s(10);
Console.WriteLine(g());
}
}

две анонимные функции захватывают один экземпляр локальной переменной x и поэтому они могут «взаимодействовать» через эту переменную. Вывод в данном примере имеет вид:

5
10

7.14.5 Вычисление выражений анонимных функций

Анонимная функция F всегда должна преобразовываться в тип делегата D или тип дерева выражения E либо напрямую, либо с помощью выполнения выражения создания делегата new D(F). Это преобразование определяет результат анонимной функции, как описано в разделе §6.5.

7.15 Выражения запросов

Выражения запросов представляют собой подмножество синтаксических конструкций языка для запросов, похожих запросы иерархических или реляционных языков запросов, таких как SQL и XQuery.

выражение запроса:
предложение from тело запроса

предложение from:
from типнеобяз идентификатор in выражение

тело запроса:
предложения тела запросанеобяз предложение select или group продолжение запросанеобяз

предложения тела запроса:
предложение тела запроса
предложения тела запроса предложение тела запроса

предложение тела запроса:
предложение from
предложение let
предложение where
предложение join
предложение join into
предложение orderby

предложение let:
let идентификатор = выражение

предложение where:
where логическое выражение

предложение join:
join типнеобяз идентификатор in выражение on выражение equals выражение

предложение join into:
join типнеобяз идентификатор in выражение on выражение equals выражение into идентификатор

предложение orderby:
orderby упорядочения

упорядочения:
упорядочение
упорядочения , упорядочение

упорядочение:
выражение направление упорядочениянеобяз

направление упорядочения:
ascending
descending

предложение select или group:
предложение select
предложение group

предложение select:
select выражение

предложение group:
group выражение by выражение

продолжение запроса:
into идентификатор тело запроса

Выражение запроса начинается с предложения from и заканчивается предложением select или group. После исходного предложения from могут идти предложения from, let, where, join или orderby. Каждое предложение from является генератором, предлагающим переменную диапазона, которая включает элементы последовательности. Каждое предложение let вводит переменную диапазона, которая представляет значение, вычисляемое с помощью предыдущих переменных диапазона. Каждое предложение where является фильтром для исключения элементов из результата. Каждое предложение join сравнивает указанные ключи исходной последовательности с ключами другой последовательности, выдавая совпадающие пары. Каждое предложение orderby изменят порядок элементов в соответствии с указанными критериями. Конечное предложение select или group задает формат результата в виде переменных диапазона. И наконец, предложение into можно использовать для «склеивания» запросов, рассматривая результаты одного запроса в качестве генератора для последующего запроса.

7.15.1 Неоднозначность в выражениях запросов

Выражения запросов содержат определенное число «контекстных ключевых слов», то есть идентификаторов, у которых есть особое значение в конкретном контексте. В частности, это from, where, join, on, equals, into, let, orderby, ascending, descending, select, group и by. Чтобы не допустить появления неоднозначности в выражениях запросов, вызванной смешанным использованием этих идентификаторов в виде ключевых слов и простых имен, при появлении в любом месте выражения запроса такие идентификаторы считаются ключевыми словами.

В этом смысле выражением запроса является любое выражение, которое начинается со строки «from идентификатор», за которым следует любая лексема кроме «, «=» или «.

Чтобы использовать эти слова в качестве идентификаторов в выражении запроса, перед ними можно указать «@» (§2.4.2).

7.15.2 Перевод выражений запросов

В языке C# не задается семантика выполнения выражений запросов. Вместо этого выражения запросов переводятся в вызовы методов, которые соответствуют шаблону выражения запроса (§7.15.3). В частности, выражения запросов переводятся в вызовы методов с именами Where, Select, SelectMany, Join, GroupJoin, OrderBy, OrderByDescending, ThenBy, ThenByDescending, GroupBy и Cast. Эти методы должны иметь специальные подписи и типы результатов, как описано в разделе §7.15.3. Эти методы могут быть методами экземпляра запрашиваемого объекта или методами расширения, внешними для объекта, и в них может реализовываться фактическое выполнение запроса.



  4   5   6   7   8   9   10   11   12   13   14   15   16   17   18   19   Наступна

Pragma warning 1 страница | Pragma warning 10 страница | Pragma warning 13 страница | Pragma warning 14 страница | Pragma warning 17 страница | System.ValueType | Break, continue и goto 23 страница | Checked и unchecked 4 страница | Checked и unchecked 5 страница | Groupby 1 страница |

© um.co.ua - учбові матеріали та реферати