我有一个带有 lambda 表达式的函数,例如:
int maxOccurrences = ( from field in data select field ).Max( f => f.Occurrences )
附言我确信上面的陈述有更好/更整洁/更惯用的版本,知道它可能是什么可能会很好,尽管它对问题并不重要!
如果我在调试时修改了函数中的任何其他内容,比如 Console.Write
表达式,调试器会指出:
Modifying a 'method' which contains a lambda expression will prevent the debug session from continuing while Edit and Continue is enabled.
我想知道为什么会这样?
我本以为为 lamba 函数和 Console.Write
语句生成的 IL 是分开的,调试器可以在必要时更改和修改。关于 lamda 功能,我是否遗漏了一些基本概念?
并不是说在所有情况下都不可能实现(我不认为)。不过,开发这将是一个巨大的功能。
当您的方法中有 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 查询的结果时,正在为 data
中的每个 field
构建此编译器生成类型的实例> 并且为支持 f => f.Occurrences
lambda 表达式而生成的该类型的单一方法被调用以计算 Max
。
edit-and-continue 的问题在于,如果正在编辑的方法中的 lambda 表达式有任何更改,则需要更改生成的类型,这不是一个选项。人们会认为在 lambda 表达式本身没有任何改变的情况下仍然可以这样做;只要捕获相同的局部变量并且匿名方法不变,在调试时修改具有这些特征的方法应该是可行的,就像在 VS 中的“普通”方法一样。
但如您所见,类型生成通常用于支持匿名方法,因此 LINQ 查询特别为“编辑并继续”过程增加了大量复杂性,并且在许多情况下使它不可能(因为它需要完全改变生成的类型)。
我认为它只是决定在假设它可以工作的有限场景中甚至费心尝试支持这种行为是不值得的开发成本。