考虑以下代码:
public ModelView(Model model) : this()
{
Loaded += (object sender, RoutedEventArgs e) =>
{
DataContext = model;
};
}
当Loaded
事件再次运行时,参数model
会出现在内存中,但它从未明确保存过,是吗?
答案 0 :(得分:4)
当您创建匿名方法或lambda时,编译器会在幕后创建一个新类,其中包含一些内部名称,如<ModelView>ctor_0
或类似内容。这个类有一个方法,它是lambda的内容,但它也有 capture 属性,其中定义了lambda的本地函数状态,并使它可用于lambda。
请参阅MSDN上Lambda Expression文档中的 Lambda Expressions中的变量范围部分:
以下规则适用于lambda表达式中的变量范围:
- 在引用它的委托变得有资格进行垃圾回收之前,捕获的变量不会被垃圾收集。 lambda表达式中引入的变量在外部方法中不可见。
- lambda表达式无法直接从封闭方法中捕获ref或out参数。
- lambda表达式中的return语句不会导致封闭方法返回。
- 如果跳转语句的目标位于块之外,则lambda表达式不能包含lambda函数内的goto语句,break语句或continue语句。如果目标在块内,则在lambda函数块外部使用跳转语句也是错误的。
答案 1 :(得分:2)
除了@ Avner的回答,这就是C#编译器(有点)为你生成的内容:
public ModelView(Model model) : this()
{
var closure = new AnonymousClass { _this = this, model = model };
Loaded += closure.Loaded;
}
private class AnonymousClass
{
public ModelView _this;
public Model model;
public void Loaded(object sender, RoutedEventArgs e)
{
_this.DataContext = model;
}
}