Студопедия Главная Случайная страница Обратная связь

Разделы: Автомобили Астрономия Биология География Дом и сад Другие языки Другое Информатика История Культура Литература Логика Математика Медицина Металлургия Механика Образование Охрана труда Педагогика Политика Право Психология Религия Риторика Социология Спорт Строительство Технология Туризм Физика Философия Финансы Химия Черчение Экология Экономика Электроника

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





Методы Sum можно, например, использовать для вычисления сумм из списка строк с деталями заказов.

class Detail
{
public int UnitCount;
public double UnitPrice;
...
}

void ComputeSums() {
ItemList<Detail> orderDetails = GetOrderDetails(...);
int totalUnits = orderDetails.Sum(d => d.UnitCount);
double orderTotal = orderDetails.Sum(d => d.UnitPrice * d.UnitCount);
...
}

В первом вызове orderDetails.Sum оба метода Sum применимы, поскольку анонимная функция d => d.UnitCount совместима и с Func<Detail,int> и с Func<Detail,double>. Однако при разрешении перегрузки будет выбран первый метод Sum, потому что преобразование в Func<Detail,int> оказывается лучше преобразования в Func<Detail,double>.

Во втором вызове orderDetails.Sum применим только второй метод Sum, потому что анонимная функция d => d.UnitPrice * d.UnitCount возвращает значение типа double. Поэтому в данном вызове при разрешении перегрузки будет выбран второй метод Sum.

7.15.4 Анонимные функции и динамическая привязка

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

7.15.5 Внешние переменные;

Любая локальная переменная, параметр значения или массив параметров, область действия которого включает лямбда_выражение или выражение_анонимного_метода, называется внешней переменной анонимной функции. В функции-члене экземпляра для класса значение this считается параметром значения и является внешней переменно любой анонимной функции, содержащейся в функции-члене.

7.15.5.1 Захваченные внешние переменные

Когда анонимная функция ссылается на внешнюю переменную, внешнюю переменную называют захваченной анонимной функцией. Обычно срок жизни локальной переменной ограничен выполнением блока или оператора, с которым она связана (§5.1.7). Однако срок жизни захваченной внешней переменной увеличивается по крайней мере до того, как делегат или дерево выражения, созданное из анонимной функции, становится объектом для процесса сборки мусора.

В примере

using System;

delegate int D();

class Test
{
static D F() {
int x = 0;
D result = () => ++x;
return result;
}

static void Main() {
D d = F();
Console.WriteLine(d());
Console.WriteLine(d());
Console.WriteLine(d());
}
}

локальная переменная x захватывается анонимной функцией и ее срок жизни увеличивается по крайней до тех пор, пока делегат, возвращенный из F, не станет объектом для процесса сборки мусора (что произойдет только в самом конце программы). Поскольку каждый вызов анонимной функции работает с одним экземпляром x, пример имеет следующий вывод:

1
2
3

Когда локальная переменная или параметр значения захватывается анонимной функцией, локальная переменная или параметр больше не считается фиксированной переменной (§18.3), а вместо этого считается перемещаемой переменной. Поэтому в любом небезопасном коде, который получает адрес захваченной внешней переменной, сначала необходимо использовать оператор fixed, чтобы зафиксировать переменную.

Заметьте, в отличие от незахваченной переменной, захваченная локальная переменная может быть одновременно использоваться в нескольких потоках выполнения.

7.15.5.2 Создание экземпляров локальных переменных

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

static void F() {
for (int i = 0; i < 3; i++) {
int x = i * 2 + 1;
...
}
}

Однако если перенести объявления x за пределы цикла, то экземпляр x будет создаваться только один раз.

static void F() {
int x;
for (int i = 0; i < 3; i++) {
x = i * 2 + 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.15.6 Вычисление выражений анонимных функций

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

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

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







Дата добавления: 2015-09-07; просмотров: 454. Нарушение авторских прав; Мы поможем в написании вашей работы!




Функция спроса населения на данный товар Функция спроса населения на данный товар: Qd=7-Р. Функция предложения: Qs= -5+2Р,где...


Аальтернативная стоимость. Кривая производственных возможностей В экономике Буридании есть 100 ед. труда с производительностью 4 м ткани или 2 кг мяса...


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


Расчетные и графические задания Равновесный объем - это объем, определяемый равенством спроса и предложения...

Этические проблемы проведения экспериментов на человеке и животных В настоящее время четко определены новые подходы и требования к биомедицинским исследованиям...

Классификация потерь населения в очагах поражения в военное время Ядерное, химическое и бактериологическое (биологическое) оружие является оружием массового поражения...

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

Индекс гингивита (PMA) (Schour, Massler, 1948) Для оценки тяжести гингивита (а в последующем и ре­гистрации динамики процесса) используют папиллярно-маргинально-альвеолярный индекс (РМА)...

Методика исследования периферических лимфатических узлов. Исследование периферических лимфатических узлов производится с помощью осмотра и пальпации...

Роль органов чувств в ориентировке слепых Процесс ориентации протекает на основе совместной, интегративной деятельности сохранных анализаторов, каждый из которых при определенных объективных условиях может выступать как ведущий...

Studopedia.info - Студопедия - 2014-2024 год . (0.015 сек.) русская версия | украинская версия