Студопедия — Try-catch-finally 13 страница
Студопедия Главная Случайная страница Обратная связь

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

Try-catch-finally 13 страница






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

Допускаются (но не являются обязательными) преобразования семантически идентичных анонимных функций с одинаковым (возможно пустым) набором экземпляров внешних переменных к одному типу делегата. В результате таких преобразований возвращается один экземпляр делегата. Термин «семантически идентичные» означает, что выполнение анонимных функций с одинаковыми аргументами во всех случаях дает одинаковые результаты. Это правило позволяет оптимизировать код, аналогичный приведенному ниже.

delegate double Function(double x);

class Test
{
static double[] Apply(double[] a, Function f) {
double[] result = new double[a.Length];
for (int i = 0; i < a.Length; i++) result[i] = f(a[i]);
return result;
}

static void F(double[] a, double[] b) {
a = Apply(a, (double x) => Math.Sin(x));
b = Apply(b, (double y) => Math.Sin(y));
...
}
}

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

6.5.2 Вычисление преобразования анонимной функции к типу дерева выражений

В результате преобразования анонимной функции к типу дерева выражений создается дерево выражений (§4.6). Точнее говоря, в результате вычисления преобразования анонимной функции создается объектная структура, представляющая саму функцию. Точная структура дерева выражений, а также процесс его построения указываются при реализации.

6.5.3 Пример реализации;

В данном разделе описывается возможная реализация преобразования анонимных функций в терминах других конструкций C#. Приведенная реализация базируется на принципах, используемых компилятором Microsoft C#, и не является ни обязательной, ни единственно возможной. Здесь приводится лишь краткое описание преобразований к дереву выражений, поскольку полная семантика таких преобразований в данной спецификации не рассматривается.

Далее в разделе рассматривается несколько примеров кода, содержащих анонимные функции с различными характеристиками. Для каждого примера представлен соответствующий код, в котором используются только другие конструкции C#. В данных примерах идентификатор D представляет следующий тип делегата:

public delegate void D();

Анонимная функция простейшего вида не записывает внешние переменные:

class Test
{
static void F() {
D d = () => { Console.WriteLine("test"); };
}
}

Это можно преобразовать в код создания экземпляра делегата, ссылающегося на создаваемый компилятором статический метод, в который помещается код анонимной функции:

class Test
{
static void F() {
D d = new D(__Method1);
}

static void __Method1() {
Console.WriteLine("test");
}
}

В следующем примере анонимная функция ссылается на члены экземпляра this:

class Test
{
int x;

void F() {
D d = () => { Console.WriteLine(x); };
}
}

Это можно преобразовать в создаваемый компилятором метод экземпляра, содержащий код анонимной функции:

class Test
{
int x;

void F() {
D d = new D(__Method1);
}

void __Method1() {
Console.WriteLine(x);
}
}

В этом примере анонимная функция записывает локальную переменную:

class Test
{
void F() {
int y = 123;
D d = () => { Console.WriteLine(y); };
}
}

Время существования локальной переменной необходимо увеличить как минимум до времени существования делегата анонимной функции. Для этого можно поместить (поднять) локальную переменную в поле создаваемого компилятором класса. В этом случае создание экземпляра локальной переменной (§7.15.5.2) будет соответствовать созданию экземпляра класса компилятором. Обращение к локальной переменной будет соответствовать обращению к полю экземпляра создаваемого компилятором класса. Кроме того, анонимная функция становится методом экземпляра создаваемого компилятором класса:

class Test
{
void F() {
__Locals1 __locals1 = new __Locals1();
__locals1.y = 123;
D d = new D(__locals1.__Method1);
}

class __Locals1
{
public int y;

public void __Method1() {
Console.WriteLine(y);
}
}
}

Следующая анонимная функция записывает this, а также две локальные переменные с различным временем существования:

class Test
{
int x;

void F() {
int y = 123;
for (int i = 0; i < 10; i++) {
int z = i * 2;
D d = () => { Console.WriteLine(x + y + z); };
}
}
}

Здесь компилятором создается класс для каждого блока оператора, в котором выполняется запись локальных переменных. За счет этого локальные переменные в каждом блоке имеют различное время существования. Экземпляр класса __Locals2, создаваемого компилятором для внутреннего блока оператора, включает в себя локальную переменную z и поле, содержащее ссылку на экземпляр __Locals1. Экземпляр класса __Locals1, создаваемого компилятором для внешнего блока оператора, включает в себя локальную переменную y и поле, содержащее ссылку на объект this включающей функции-члена. При такой структуре данных с помощью экземпляра __Local2 возможно обращение ко всем записанным внешним переменным. Таким образом, код анонимной функции реализуется как метод экземпляра этого класса.

class Test
{
void F() {
__Locals1 __locals1 = new __Locals1();
__locals1.__this = this;
__locals1.y = 123;
for (int i = 0; i < 10; i++) {
__Locals2 __locals2 = new __Locals2();
__locals2.__locals1 = __locals1;
__locals2.z = i * 2;
D d = new D(__locals2.__Method1);
}
}

class __Locals1
{
public Test __this;
public int y;
}

class __Locals2
{
public __Locals1 __locals1;
public int z;

public void __Method1() {
Console.WriteLine(__locals1.__this.x + __locals1.y + z);
}
}
}

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







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



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

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

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

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

Ведение учета результатов боевой подготовки в роте и во взводе Содержание журнала учета боевой подготовки во взводе. Учет результатов боевой подготовки - есть отражение количественных и качественных показателей выполнения планов подготовки соединений...

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

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

Дезинфекция предметов ухода, инструментов однократного и многократного использования   Дезинфекция изделий медицинского назначения проводится с целью уничтожения патогенных и условно-патогенных микроорганизмов - вирусов (в т...

Машины и механизмы для нарезки овощей В зависимости от назначения овощерезательные машины подразделяются на две группы: машины для нарезки сырых и вареных овощей...

Классификация и основные элементы конструкций теплового оборудования Многообразие способов тепловой обработки продуктов предопределяет широкую номенклатуру тепловых аппаратов...

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