18

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?

Rob
  • 26,989
  • 16
  • 82
  • 98
TK.
  • 46,577
  • 46
  • 119
  • 147

3 Answers3

14

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.

Dan Tao
  • 125,917
  • 54
  • 300
  • 447
1

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

Stas Sh
  • 656
  • 4
  • 8
  • 1
    Link in answer is outdated. – Pang Jul 14 '21 at 03:47
  • Just double checked, the same feature is also supported in newer versions of Visual Studio. The feature is called "Edit and Continue" and in the list of supported changes that do not require restart of the process it still has lambda expressions and LINQ - https://learn.microsoft.com/en-us/visualstudio/debugger/supported-code-changes-csharp?view=vs-2022 – Stas Sh Nov 22 '21 at 13:28
-3

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

Bradley
  • 443
  • 4
  • 9
  • 9
    If this is so simple you should provide the code example ;) remember, it's not simple for everyone. – ForceMagic Oct 20 '12 at 02:40
  • I concur with ForceMagic – Mastro Nov 06 '13 at 16:41
  • You can't use anonymous in place from immed: "_availableTypeCache.FirstOrDefault(delegate(Type t) { return t;}) Expression cannot contain anonymous methods" You have to drop to LINQ with a var that is outside the scope of the LINQ call. – John S. Nov 16 '13 at 20:26
  • @ForceMagic. That is one of the best answers I have heard on Stack. There are different levels of understanding, and yet, some might be advanced in one sector, but have not needed to use something from another sector. Great response, and I can see you are a great addition to the social environment of stack. – Casey ScriptFu Pharr Dec 17 '13 at 16:09
  • @Bradley if this is possible, could you give a reference or a code sample – Arun Prasad E S Jun 11 '16 at 07:59