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

发布于 2024-10-14 03:44:47 字数 471 浏览 0 评论 0原文

我有一个带有 lambda 表达式的函数,类似于:

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

PS 我确信上述语句有一个更好/更简洁/更惯用的版本,很高兴知道它可能是什么,尽管它对问题并不重要!

如果我在调试时修改函数中的任何其他内容(例如 Console.Write 表达式),调试器会指出:

修改包含 lambda 表达式的“方法”将阻止调试会话在启用“编辑并继续”时继续。

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

我本以为为lambda 函数生成的IL 和Console.Write 语句将是分开的,并且调试器可以在必要时更改和修改。关于 lamda 功能,我是否缺少一些基本概念?

I have a function with a lambda expression something like:

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

P.S. I'm sure that there's a nicer / neater / more idiomatic version of the above statement, it might be nice to know what that might be, although its not important to the question!

If I modify anything else within the function whilst debugging say a Console.Write expression, the debugger states:

Modifying a 'method' which contains a lambda expression will prevent the debug session from continuing while Edit and Continue is enabled.

I was wondering why this might be the case?

I would have thought that the IL generated for the lamba function and the Console.Write statement would be separate and that the Debugger could alter and modify when necessary. Is there some fundamental concept that I'm missing concerning the lamda functionality?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

ま柒月 2024-10-21 03:44:47

这并不是说在所有情况下都不可能实现(我不这么认为)。不过,这将是一个需要开发的怪物功能。

当您的方法中包含 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

编辑并继续的问题是,如果正在编辑的方法中的 lambda 表达式发生任何更改,则需要更改生成的类型,而这不是一个选项。人们可能会认为,在 lambda 表达式本身没有任何改变的情况下,这仍然可以完成;只要捕获相同的局部变量并且匿名方法不变,在调试时修改具有这些特征的方法应该是可行的,就像 VS 中的“正常”方法一样。

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

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

It isn't that it would be impossible to achieve in all cases (I don't think). It would be a monster feature to develop, though.

When you've got LINQ syntax in your method, generally that involves some anonymous method either behind-the-scenes:

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

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

...or just flat-out in front of the scenes (as in your example):

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

An anonymous method in turn gets compiled into a type with instance methods to support the code you've written.

In the example above, consider the f => f.Occurrences lambda. This gets compiled into a type with a single instance field whose type is that of the local f in that lambda; this type contains a method that returns f.Occurrences.

So when the code ultimately enumerates over the result of your LINQ query, what's happening is that an instance of this compiler-generated type is being constructed for every field in data and that type's single method which has been generated to support the f => f.Occurrences lambda expression is being called to calculate Max.

The issue with edit-and-continue is that if there's any change to the lambda expressions in the method being edited, this necessitates changing the types generated, which is not an option. One would think this could still be done in the case where nothing is altered about the lambda expressions themselves; as long as the same locals are captured and the anonymous methods are unchanged, it should be feasible to modify a method with these characteristics while debugging just as it is for "normal" methods in VS.

But as you can see, the type generation used to support anonymous methods in general and therefore LINQ queries specifically adds a great deal of complexity to the edit-and-continue process, and in many cases makes it impossible (since it requires changing generated types completely).

I think it was just decided that it wasn't worth the development cost to even bother trying to support this behavior in the limited scenarios where it could hypothetically work.

天涯离梦残月幽梦 2024-10-21 03:44:47

或者您可以简单地迁移到 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

Or you can simply move to Visual Studio 2015 :)

The "Edit and Continue" feature in VS 2015 allows editing methods with lambda expressions.

You can read about it in more detail here:

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

泪痕残 2024-10-21 03:44:47

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

There is a really simple way to debug a lamba expression. Convert it to an anonymous method using an inline delegate. Simple. :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文