3 回答
TA贡献1804条经验 获得超8个赞
Lambda表达式就像匿名方法一样,实际上是非常复杂的野兽。即使我们排除Expression
(.NET 3.5),仍然留下了很多复杂性,尤其是捕获的变量,这些变量从根本上重新构造了使用它们的代码(您认为变量成为编译器生成的类中的字段) ,有一点烟雾和镜子。
因此,您可以无所事事地使用它们,我一点也不感到惊讶-有很多支持这种魔术的编译器工作(以及幕后的类型生成)。
TA贡献1815条经验 获得超10个赞
不,您不能在watch / locals /即时窗口中使用lambda表达式。正如Marc所指出的那样,这非常复杂。不过,我想进一步探讨这个话题。
大多数人在调试器中执行匿名函数时不会考虑的是,它不会在真空中发生。定义和运行匿名函数的行为改变了代码库的基础结构。通常,尤其是从即时窗口更改代码是一项非常困难的任务。
考虑以下代码。
void Example() {
var v1 = 42;
var v2 = 56;
Func<int> func1 = () => v1;
System.Diagnostics.Debugger.Break();
var v3 = v1 + v2;
}
此特定代码创建一个单个闭包以捕获值v1。每当匿名函数使用在其作用域之外声明的变量时,都需要捕获闭包。出于所有意图和目的,此功能中不再存在v1。最后一行实际上更像以下内容
var v3 = closure1.v1 + v2;
如果在调试器中运行示例函数,它将在中断行处停止。现在,假设用户是否在监视窗口中输入了以下内容
(Func<int>)(() => v2);
为了正确执行此操作,调试器(或更合适的EE)将需要为变量v2创建一个闭包。这很难但并非不可能。
对于EE而言,真正使这项工作变得艰难的是最后一行。现在应该如何执行该行?出于所有目的和目的,匿名函数删除了v2变量,并将其替换为closure2.v2。所以现在实际上需要阅读最后一行代码
var v3 = closure1.v1 + closure2.v2;
然而,要在代码中实际获得这种效果,则EE必须更改最后一行代码,这实际上是ENC动作。尽管可以使用此特定示例,但大部分情况都不可行。
更糟糕的是执行lambda表达式不应创建新的闭包。它实际上应该将数据附加到原始闭包中。此时,您会直接遇到ENC的限制。
不幸的是,我的小例子只能解决我们遇到的问题。我一直说我会写一篇完整的博客文章,希望这个周末有时间。
- 3 回答
- 0 关注
- 994 浏览
添加回答
举报