Студопедия — 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; просмотров: 546. Нарушение авторских прав; Мы поможем в написании вашей работы!



Композиция из абстрактных геометрических фигур Данная композиция состоит из линий, штриховки, абстрактных геометрических форм...

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

ТЕОРЕТИЧЕСКАЯ МЕХАНИКА Статика является частью теоретической механики, изучающей условия, при ко­торых тело находится под действием заданной системы сил...

Теория усилителей. Схема Основная масса современных аналоговых и аналого-цифровых электронных устройств выполняется на специализированных микросхемах...

Понятие о синдроме нарушения бронхиальной проходимости и его клинические проявления Синдром нарушения бронхиальной проходимости (бронхообструктивный синдром) – это патологическое состояние...

Опухоли яичников в детском и подростковом возрасте Опухоли яичников занимают первое место в структуре опухолей половой системы у девочек и встречаются в возрасте 10 – 16 лет и в период полового созревания...

Способы тактических действий при проведении специальных операций Специальные операции проводятся с применением следующих основных тактических способов действий: охрана...

Виды нарушений опорно-двигательного аппарата у детей В общеупотребительном значении нарушение опорно-двигательного аппарата (ОДА) идентифицируется с нарушениями двигательных функций и определенными органическими поражениями (дефектами)...

Особенности массовой коммуникации Развитие средств связи и информации привело к возникновению явления массовой коммуникации...

Тема: Изучение приспособленности организмов к среде обитания Цель:выяснить механизм образования приспособлений к среде обитания и их относительный характер, сделать вывод о том, что приспособленность – результат действия естественного отбора...

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