C#调试包含lambda表达式的函数

时间:2011-01-24 14:24:51

标签: c# debugging lambda

我有一个带有lambda表达式的函数,如:

int maxOccurrences = ( from field in data select field ).Max( f => f.Occurrences )

P.S。我确信上面的陈述有一个更好/更整洁/更惯用的版本,可能很高兴知道这可能是什么,虽然它对这个问题不重要!

如果我在调试中调用Console.Write表达式时修改了函数中的任何其他内容,则调试器会声明:

  

修改包含lambda表达式的'method'将阻止调试会话在启用Edit and Continue时继续。

我想知道为什么会出现这种情况?

我原本认为为lamba函数和Console.Write语句生成的IL将是独立的,并且调试器可以在必要时进行更改和修改。有没有关于lamda功能的一些基本概念?

3 个答案:

答案 0 :(得分:11)

在所有情况下(我不认为)并不是不可能。不过,这将是一个怪物特征。

当你的方法中有LINQ语法时,通常会涉及到幕后的一些匿名方法:

// This LINQ query...
var fields = from field in data select field;

// ...is equivalent to this:
var fields = data.Select(f => f);

...或者只是在场景前面展开(如你的例子所示):

( from field in data select field ).Max( f => f.Occurrences ) // <- lambda

反过来,匿名方法会被编译成带有实例方法的类型,以支持您编写的代码。

在上面的示例中,请考虑f => f.Occurrences lambda。这被编译成一个具有单个实例字段的类型,其类型是该lambda中本地f的类型;此类型包含一个返回f.Occurrences

的方法

因此,当代码最终枚举LINQ查询的结果时,正在发生的事情是,正在为field中的每个data构建此编译器生成类型的实例,并且该类型的单个方法已调用已生成以支持f => f.Occurrences lambda表达式来计算Max

编辑并继续的问题是,如果对正在编辑的方法中的lambda表达式进行任何更改,则必须更改生成的类型,这不是一个选项。有人会认为在lambda表达式本身没有任何改变的情况下仍然可以做到这一点;只要捕获了相同的本地并且匿名方法没有改变,在调试时修改具有这些特征的方法应该是可行的,就像在VS中使用“普通”方法一样。

但正如您所看到的,一般用于支持匿名方法的类型生成因此LINQ查询特别为编辑和继续过程添加了大量复杂性,并且在许多情况下使它变得不可能(因为它需要完全改变生成的类型)。

我认为只是决定开发成本不值得尝试在可以假设工作的有限场景中支持这种行为。

答案 1 :(得分:1)

或者您可以简单地转到Visual Studio 2015:)

VS 2015中的“编辑并继续”功能允许使用lambda表达式编辑方法。

您可以在此处详细了解:

http://blogs.msdn.com/b/visualstudioalm/archive/2015/04/29/net-enc-support-for-lambdas-and-other-improvements-in-visual-studio-2015.aspx

答案 2 :(得分:-3)

调试lambda表达式有一种非常简单的方法。使用内联委托将其转换为匿名方法。简单。 :)