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

标签 c# debugging lambda

<分区>

我有一个带有 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 查询特别为“编辑并继续”过程增加了大量复杂性,并且在许多情况下使它不可能(因为它需要完全改变生成的类型)。

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

关于C# 调试包含 lambda 表达式的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4783085/

相关文章:

c# - 将 float 转换为 byte[] 以通过命名管道发送 (C++)

java - 无法使用 Eclipse 在 Java 中进行调试

linux - 逐行专门调试

python - flatMap 函数 : rdd. flatMap(lambda x : map(lambda e: (x[0], e), x[1])) 中 lambda 函数的解释?

c# - 如何在不等待 C# 中被调用函数完成的情况下继续执行函数

c# - 我们如何在 ItemProviderDelegate 中等待 Action/Effect 的结果?

c# - winforms 连接到 SQL Server 的理想设计。

c - 使用 malloc 声明变量如何导致丢失位?

c++ - 如何从 lambda-functor 的主体中增加一个变量?

java - TableColumn::setOnEditCommit() 中的 Lambda 运算符