匿名委托关闭(或者为什么这有效)?
下面的代码直接取自 MSDN 介绍 MVVM 设计的文章附带的示例项目模式。我不太明白为什么委托会看到“handler”的值而不是 null。我的理解是,为委托方法创建的闭包包含范围内到目前为止在执行中已初始化的所有变量,并且由于在创建委托后重新分配“处理程序”,闭包将包含设置为 null 的“处理程序” 。
康斯坦丁
EventHandler handler = null;
handler = delegate
{
viewModel.RequestClose -= handler;
window.Close();
};
viewModel.RequestClose += handler;
The code below is taken directly from the sample project accompanying the article on MSDN introducing MVVM design pattern. I do not quite understand why the delegate sees the value of 'handler' other than null. My understanding was that the closure created for the delegate method contains all variables in scope that have been initialized up to this point in the execution, and since 'handler' is reassigned after the delegate is created the closure will contain 'handler' set to null.
Konstantin
EventHandler handler = null;
handler = delegate
{
viewModel.RequestClose -= handler;
window.Close();
};
viewModel.RequestClose += handler;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
委托捕获变量
handler
,而不是变量的内容。当您查看 C# 编译器将代码编译为什么(例如使用 Reflector)时,情况会变得更加清楚。您的代码大致编译为:
The delegate captures the variable
handler
, not the contents of the variable.It becomes more clear when you look at what the C# compiler compiles your code to, e.g., using Reflector. Your code is compiled roughly to this:
像这样写:
要得到错误CS0165:使用未分配的局部变量“处理程序”。
有问题的诊断,它实际上并不是未分配的。事实上,实现匿名方法的隐藏类是在分配捕获的“handler”值之前创建的。不过,这在 C# 编译器中实现起来并不容易。边缘情况。
Write it like this:
To get error CS0165: Use of unassigned local variable 'handler'.
Questionable diagnostic, it isn't actually unassigned. The hidden class that implements the anonymous method does in fact get created before the captured value of 'handler' is assigned. That cannot be easy to implement in the C# compiler though. Edge case.
闭包不复制变量,它维护一个引用。当创建委托并设置处理程序时,此更改将被更新。
A closure doesn't copy the variables, it maintains a reference. When the delegate is created and the handler is set, this change is updated.
处理程序在分配之前初始化:
编译为:
The handler is initialised before asigning:
Compiles to: