views:

400

answers:

3

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.

A: 

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.

Jon Skeet
I agree...., but it's not an answer to the question.
Kai
I knew you'd know the answer ;-)
Kai
IMO the answer to many questions is to avoid getting into the painful situation to start with.
Jon Skeet
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.
Eyvind
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)
Jon Skeet
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.)
Jon Skeet
I agree - now I just need to sell the idea to management :)
Eyvind
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).
leppie
+2  A: 

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.

Anton Gogolev
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...
Eyvind
+7  A: 

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 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 is 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 class which are already alive in the processe

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.

JaredPar
Straight from the horse's mouth. +1
Jon Skeet
@Jon We've had many internal meetings on this subject and I've had to give this presentation many times. I really need to write a full blown doc on the subject. Blogging seems like a good place for it. There is hope that this will be solved in a future version of VS.
JaredPar
Please do write a blog about it.
Eyvind