Why can I not edit a method that contains an anonymous method in the debugger?
Asked Answered
C

5

21

So, every time I have written a lambda expression or anonymous method inside a method that I did not get quite right, I am forced to recompile and restart the entire application or unit test framework in order to fix it. This is seriously annoying, and I end up wasting more time than I saved by using these constructs in the first place. It is so bad that I try to stay away from them if I can, even though Linq and lambdas are among my favourite C# features.

I suppose there is a good technical reason for why it is this way, and perhaps someone knows? Furthermore, does anyone know if it will be fixed in VS2010?

Thanks.

Chromonema answered 24/2, 2009 at 14:38 Comment(0)
B
21

Yes there is a very good reason for why you cannot do this. The simple reason is cost. The cost of enabling this feature in C# (or VB) is extremely high.

Editing a lambda function is a specific case of a class of ENC issues that are very difficult to solve with the current ENC (Edit'n'Continue) architecture. Namely, it's very difficult to ENC any method which where the ENC does one of the following:-

  1. Generates Metadata in the form of a class
  2. Edits or generates a generic method

The first issue is more of a logic constraint but it also bumps into a couple of limitations in the ENC architecture. Namely the problem is generating the first class isn't terribly difficult. What's bothersome is generating the class after the second edit. The ENC engine must start tracking the symbol table for not only the live code, but the generated classes as well. Normally this is not so bad, but this becomes increasingly difficult when the shape of a generated class is based on the context in which it is used (as is the case with lambdas because of closures). More importantly, how do you resolve the differences against instances of the classes that are already alive in the process?

The second issue is a strict limitation in the CLR ENC architecture. There is nothing that C# (or VB) can do to work around this.

Lambdas unfortunately hit both of these issues dead on. The short version is that ENC'ing a lambda involves lots of mutations on existing classes (which may or may not have been generated from other ENC's). The big problem comes in resolving the differences between the new code and the existing closure instances alive in the current process space. Also, lambdas tend to use generics a lot more than other code and hit issue #2.

The details are pretty hairy and a bit too involved for a normal SO answer. I have considered writing a lengthy blog post on the subject. If I get around to it I'll link it back into this particular answer.

Berke answered 24/2, 2009 at 15:15 Comment(6)
Is this something that you need to prove that the VS using community wants? I feel there's a lot of momentum headed towards functional programming style and generic type inference, both of which tend to sprinkle lambdas in methods. It's rare for me to write methods with no lambdas.Heroin
@marr75, The VS team is very much aware of the customer desire for better support for lambdas in debugging scenarios (ENC + watch, locals, etc ...) and the feature comes up for consideration practically every release. Unfortunately though it is a very expensive feature. I wrote 2 blog articles on the subject that attempts to break down the feature and explain the complexity and hence high cost. blogs.msdn.com/b/jaredpar/archive/2010/06/02/…Berke
It would be at least nice to add support for edit & continue when changes won't affect generated class (same fields, same properties etc...). It would solve at least 80% of cases in 20% of effort. I often edit function with lambda, but not lambda itself. Sometimes I modify lambda, but it won't change anonymous type.Decease
@Blackfighter VB.Net already has support for this but C# is still lackingBerke
Am I the only one that it took a minute to get what ENC referred to? Perhaps some caffeine is in order...Romero
It is possible now in the latest VS right?Priestridden
O
1

According to a list of Supported Code Changes, you cannot add fields to existing types. Anonymous methods are compiled into oddly-named classes (kinda <>_c__DisplayClass1), which are precisely that: types. Even though your modifications to the anonymous method may not include changing the set of enclosed variables (adding those would alter fields of an existing class), I guess that's the reason it's impossible to modify anonymous methods.

Orchidectomy answered 24/2, 2009 at 14:56 Comment(1)
You don't have to modify the anonymous method itself for this problem to manifest itself, it is enough to modify a method that contains an anonymous method, and it seems that even a single space is enough to tic it off...Chromonema
L
1

It is a bit a shame that this feature is partially supported in VB but not in C#: http://msdn.microsoft.com/en-us/library/bb385795.aspx

Implementing the same behaviour in C# would reduce the pain level by 80% for functions that contain lambda expressions, where we do not need to modify the lambda expressions nor any expression that depends on them, and probably not for a "monster cost".

Loretaloretta answered 25/5, 2011 at 16:33 Comment(0)
T
0

Restarting a unit test should take a matter of seconds, if that. I've never liked the "edit and continue" model to be honest - you should always rerun from scratch IMO, just in case the change midway through execution would have affected the code which ran earlier. Given that, you're better off using unit tests which can be run with a very quick turnaround. If your individual unit tests take an unbearable time to start, that's something you should look at addressing.

EDIT: As for why it doesn't work - you may find that it works for some lambdas but not others. Lambda expressions which don't capture any variables (including this) are cached in a private static variable, so that only one instance of the delegate is ever created. Changing the code means reinitialising that variable which could have interesting side-effects I suspect.

Trituration answered 24/2, 2009 at 14:50 Comment(7)
I knew you'd know the answer ;-)Unruffled
IMO the answer to many questions is to avoid getting into the painful situation to start with.Trituration
You are right, conceptually, w.r.t. the unit test framework. However, even displaying the unit test "dock window" in VS takes ages when the solution gets big enough, and it ends up stealing a lot of time, unfortunately.Chromonema
Sounds like you need to use a different test framework - it's very quick with NUnit + ReSharper. Alternatively, work with smaller solutions. I'm quite serious - if the unit test cycle is a pain, it will throw the test/code/refactor/test/code/refactor cycle out of whack. (continued)Trituration
Effort spent fixing that will usually (IMO) pay dividends very quickly. You really have to be able to launch unit tests quickly. (Integration tests and the like usually take longer, but that's not as much of a problem.)Trituration
ENC is very cool in UI apps. Given you have the structure in place, you develop the whole 'app' in a debug session (good when you have live connections too).Descartes
I am hereby nominating this to be @JonSkeet's least popular answer: Only 1 upvote at the time of this nomination (I know you guys are going to screw it up by starting to upvote after this). It's like searching on Google and only getting 1 result (plus ads)... what are the odds! Btw this is also why our politicians keep lying to us folks lolTicket
C
0

I just want to point out that Visual Studio's consideration of "editing" in this context is (or at least can be) a bit stupid. When I was checking out an older commit as part of doing an interactive rebase in git and then attempting to run an unit test, that resulted in 9 error (with ENC0014 and some others).

So with no files modified, every time I attempted to debug the unit test I got those errors. Restarting Visual Studio made the errors go away, so I guess that the underlying problem is missing cache invalidation where Visual Studio does not detect/react to files being changed outside editing via its editor windows.

Cyler answered 28/4, 2022 at 7:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.