Как лямбда-выражения работают внутри? - PullRequest
7 голосов
/ 28 октября 2009

При поиске ответа на этот вопрос: " Почему параметр out запрещен в анонимном методе? " Я немного растерялся из-за того, как на самом деле работают лямбда-выражения и анонимные методы.

В комментариях JaredPar заявляет, что «Представьте, например, что параметр out ссылается на локальную переменную в стеке. Лямбда может выполняться в любой произвольной точке в будущем и, следовательно, может выполняться, когда этот кадр стека больше не действителен» .

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

Я имею в виду нечто подобное:

public void Foo(ComplexObject val, out SomeDelegate outDelegate)
{
  ComplexObject obj = new ComplexObject(val)
  SomeDelegate = delegate(int other) { return (obj.value * other); }  
}

public void Bar()
{
  SomeDelegate MyDel = null;
  Foo(5, out MyDel);
  int finalRes = MyDel(100);
  // Whatever
}

В этой ситуации я действительно не знаю, что происходит. obj - это ссылка на стек, которая больше не будет действительной при возврате метода, поэтому анонимный метод должен иметь возможность (если это работает) фактически узнать, что это ссылочный тип, и скопировать ссылку вместо значения, если это так ... почему ref params не сработает, если «прецедент» более или менее одинаков?

Ответы [ 2 ]

8 голосов
/ 28 октября 2009

Я написал довольно обширную серию блогов о том, как замыкания работают внутри. Он написан для реализации замыканий в VB.Net, но основные детали очень похожи на C #. Он должен предоставить ответы, которые вы ищете

Вот ссылка на часть 6, которая ссылается на все остальные статьи

6 голосов
/ 28 октября 2009

Джон Скит написал подробное описание .

По сути, компилятор превращает внешний метод в класс и превращает все переменные, к которым обращаются анонимные методы, в поля класса. Анонимные методы становятся обычными методами экземпляра в классе.

...