Jar*_*Par 91

不,你不能在watch/locals/immediate窗口中使用lambda表达式.正如马克所指出的那样,这非常复杂.我想进一步深入探讨这个话题.

大多数人在调试器中执行匿名函数时没有考虑的是它不会出现在vaccuum中.定义和运行匿名函数的行为改变了代码库的底层结构.一般而言,特别是从即时窗口更改代码是一项非常困难的任务.

请考虑以下代码.

void Example() {
  var v1 = 42;
  var v2 = 56; 
  Func<int> func1 = () => v1;
  System.Diagnostics.Debugger.Break();
  var v3 = v1 + v2;
}
Run Code Online (Sandbox Code Playgroud)

此特定代码创建一个闭包以捕获值v1.只要匿名函数使用在其范围之外声明的变量,就需要关闭捕获.对于所有意图和目的,此函数中不再存在v1.最后一行实际上看起来更像是以下内容

var v3 = closure1.v1 + v2;
Run Code Online (Sandbox Code Playgroud)

如果函数Example在调试器中运行,它将在Break行停止.现在假设用户在观察窗口中输入以下内容

(Func<int>)(() => v2);
Run Code Online (Sandbox Code Playgroud)

为了正确执行它,调试器(或更合适的EE)需要为变量v2创建一个闭包.这很难但并非不可能.

真正使EE成为一项艰巨的工作的是最后一行.现在应该如何执行该行?对于所有意图和目的,匿名函数删除了v2变量并将其替换为closure2.v2.所以最后一行代码现在需要阅读

var v3 = closure1.v1 + closure2.v2;
Run Code Online (Sandbox Code Playgroud)

然而,要在代码中实际获得此效果,需要EE更改实际上是ENC操作的最后一行代码.虽然这个具体的例子是可能的,但很多场景都不是.

更糟糕的是执行lambda表达式不应该创建一个新的闭包.它实际上应该是将数据附加到原始闭包.此时,您将直接进入限制ENC.

不幸的是,我的小例子只是触及了我们遇到的问题的表面.我一直在说我会写一篇关于这个主题的完整博客文章,希望我本周末有时间.

  • 呜咽,呜咽,接受平庸,呜咽,呜咽.调试器是IDE的核心,你打破了它!观察窗口中的Lambdas不需要捕获任何东西.与任何其他监视代码一样,它们仅在特定堆栈帧时才有意义.(或者你捕获变量,移动到具有相同变量名的另一个函数......以及什么?)调试器是为了破解编译器.让它起作用! (40认同)
  • 详细信息为+1 ...我会留意该博客条目;-p (8认同)
  • 为什么它们很简单,不允许在监视窗口上的lambda上捕获变量.简单,并允许一堆调试方案,其中lambdas只是在真正的功能代码中使用. (2认同)

Mar*_*ell 64

Lambda表达式,如匿名方法,实际上是非常复杂的野兽.即使我们排除Expression(.NET 3.5),仍然会留下很多复杂性,尤其是被捕获的变量,从根本上重新构造使用它们的代码(你认为变量成为编译器生成的类的字段)带着一点烟雾和镜子.

因此,我并不会感到惊讶,你不能无所事事地使用它们 - 有很多编译工作(和幕后的类型生成)支持这种魔力.


stu*_*win 49

您不能在立即或监视窗口中使用lambda表达式.

但是,您可以使用System.Linq.Dynamic表达式,其形式为.Where("Id = @ 0",2) - 它没有标准Linq中可用的全部方法,并且没有完整的lambda表达式的力量,但是,它总比没有好!

  • 嗯...虽然其他人解释了虽然不可能,但这个至少为我们提供了一个可能的解决方案.+1 (2认同)

Ath*_*ari 21

未来来了!

Visual Studio 2015中添加了对调试lambda表达式的支持(在撰写本文时为预览版).

必须重写Expression Evaluator,因此缺少许多功能:远程调试ASP.NET,在立即窗口中声明变量,检查动态变量等.目前还不支持需要调用本机函数的lambda表达式.


Pat*_*olf 5

这可能会有所帮助:Visual Studio的扩展立即窗口(在调试中使用Linq,Lambda Expr)

一切顺利,帕特里克

  • 请注意,虽然第一个链接看起来很棒,但它处于alpha状态,并且不太可能出现(最后一次更新于2008年). (5认同)