2013-06-14 2 views
1

Являются ли анонимные методы определенными встроенными? В приведенном ниже примере объект-делегат «d» имеет ссылку на анонимный метод, который обращается к переменной «x», которая определена в методе Fun. Объем «x» должен быть ограничен методом «Fun», но когда мы вызываем MyFun, который вызывает делегат, передаваемый как параметр, и увеличивает значение «x».Являются ли анонимные методы определенными встроенными?

Выходной результат «6», как это происходит? Как значение «x», или на самом деле «переменная x» на самом деле было доступно в анонимном методе?

public delegate void Del(); 

public void Fun() 
{ 
    int x = 5; 
    Del d = delegate { x++; }; 
    MyFun(d); 
    Console.WriteLine(x); 
} 

public static void MyFun(Del d) 
{ 
    d(); 
} 

ответ

6

Являются ли анонимные методы определенными встроенными?

Я не знаю, что означает «встроенный».

В приведенном ниже примере объект-делегат «d» ссылается на анонимный метод, который обращается к переменной «x», которая определена в методе Del.

No, x определено в методе Fun. Del не метод, это тип делегата.

Сфера применения «x» должна быть ограничена методом Fun.

Исправить. Напомним, что «область действия x» определяется как «область текста программы, в которой x может быть просмотрено его неквалифицированным именем». Вы правильно используете термин; тело Fun - это объем x. Обратите внимание, что анонимный метод находится внутри Fun, и поэтому x находится в области.

При вызове MyFun он вызывает делегат, переданный как параметр, и увеличивает значение «x».

Исправить.

Выходной сигнал «6».

Исправить.

как это происходит?

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

Если у вас есть вопрос, «какой код генерирует компилятор, чтобы это произошло?» компилятор делает вид, что вы написали что-то вроде:

public delegate void Del(); 

private class Locals 
{ 
    public int x; 
    public void AnonymousMethod() { x++; } 
}  

public void Fun() 
{ 
    Locals locals = new Locals(); 
    locals.x = 5; 
    Del d = locals.AnonymousMethod; 
    MyFun(d); 
    Console.WriteLine(locals.x); 
} 

public static void MyFun(Del d) 
{ 
    d(); 
} 
+0

Эрик, это выглядит простым в случае единственной переменной «x». Что бы сгенерировал компилятор, когда мы обращаемся к «x» и некоторому «y» из некоторого объекта «z» внутри анонимного метода? Это может сойти с ума в зависимости от того, сколько переменных и объектов мы получаем в анонимном методе. – Brij

+1

@Brij: Это сайт вопросов и ответов. Мой совет заключается в том, что вы задаете этот вопрос *, и кто-то ответит на него. –

+0

@Brij: И да, он может «сойти с ума», как вы говорите. Все становится особенно сложным, если у вас есть вложенные анонимные функции, которые используют формальные параметры внешних функций в качестве захваченных переменных во внутренних функциях. Это один из самых сложных фрагментов компилятора. –

1

Это называется Closure. Он захватывает x и использует его, как только выполняется делегат. Это делается с помощью некоторой магии компилятора.

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

+0

Когда он записывает 'x'? – Brij

+0

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

+2

http://stackoverflow.com/questions/428617/what-are-closures-in-net –