为了账号安全,请及时绑定邮箱和手机立即绑定

Visual Studio调试“快速监视”工具和lambda表达式

Visual Studio调试“快速监视”工具和lambda表达式

缥缈止盈 2019-12-26 11:12:56
为什么在“快速监视”窗口中调试时不能使用lambda表达式?UPD:另请参见http://blogs.msdn.com/b/jaredpar/archive/2009/08/26/why-no-linq-in-debugger-windows.aspxhttp://blogs.msdn.com/b/jaredpar/archive/2010/06/02/why-is-linq-absent-from-debugger-windows-part-2.aspx
查看完整描述

3 回答

?
胡说叔叔

TA贡献1804条经验 获得超8个赞

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

因此,您可以无所事事地使用它们,我一点也不感到惊讶-有很多支持这种魔术的编译器工作(以及幕后的类型生成)。


查看完整回答
反对 回复 2019-12-26
?
动漫人物

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的限制。


不幸的是,我的小例子只能解决我们遇到的问题。我一直说我会写一篇完整的博客文章,希望这个周末有时间。


查看完整回答
反对 回复 2019-12-26
  • 3 回答
  • 0 关注
  • 994 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信