What happened to my code!?

This post all came out of a question I answered on stackoverflow last night.  If you want to see it it's http://stackoverflow.com/questions/128606....  The problem was that an ExcludeFromCodeCoverage attribute on a method wasn't ignoring a lambda expression in the method so it was showing as being uncovered.  The underlying reason is that the code that is run by the machine is not necessarily (and more often than not) not the code that you see when you edit your class files in your IDE.  I won't go into too much detail but when you build a project file the C# compiler converts the code that you've written into MSIL (Microsoft Intermediate Language) which is machine independent.  At a later point the JIT (just in time) compiler then translates that IL into native machine instructions but this isn't the part that we care about.  When the compiler converts the code that you've written into IL it actually does a few extra things under the hood.  For example if you declared an anonymous method it will actually go off and create a method for you.  Take for example the following bit of code.

public class SomeClass
{
    public string SomeMethod(List<string> someStrings)
    {
        return someStrings.FirstOrDefault(s => s.Equals("SomeValue"));
    }
}

A fairly simple method that takes in a list of strings and then gets the first string that is equal to "SomeValue".  If you compile this and then use a decompiler such as DotPeek (which I've been making great use of since .Net Reflector went commercial) to decompile it again you'll see the following.

Just what you expect right?  Well it is until you click the following button.

This takes you behind the scenes as it were and your DotPeek window will now look something more like this.

Now those of you who have been working with older versions of the .Net framework where anonymous methods and lambda expressions were not available might recognise roughly what has happened here.  The compiler has transformed your lambda expression into a whole bunch of extra code, if you strip out all the angle brackets* and other stuff then effectively what you're left with is the following steps.

It declares a delegate to match the lambda expresesion which looks something like this.

private static Func<string, bool> AnonymousMethodDelegate;

It then creates the named method that matches the delegate declaration.

[CompilerGenerated]
private static bool CompilerGeneratedMethod(string s)
{
    return s.Equals("SomeValue");
}

Then finally it calls into the named method using the delegate in your method something like this

public string SomeMethod(List<string> someStrings)
{
    AnonymousMethodDelegate = CompilerGeneratedMethod;
    Func<string, bool> predicate = AnonymousMethodDelegate;
    return Enumerable.FirstOrDefault<string>((IEnumerable<string>) someStrings, predicate);
}

Now as I mentioned before those of you familiar with the older versions of .Net will recognise that this is the traditional way of using delegates to invoke method calls.  The compiler has taken your code and translated it into this.  Those of you who remember the original question can probably now work out why the lambda expression was not being ignored by the ExcludeFromCodeCoverage attribute.  It's been translated into a new method by the compiler which no longer has the ExcludeFromCodeCoverage attribute attached and so isn't ignored when you run a code coverage tool such as NCover.  You can get around this if you look at the stack overflow question.

Obviously most of the time this tranformation step isn't a problem.  You won't actually care what the compiler translates your code into but it's always useful to know that what you're writing in your IDE is not necessarily the same code that the machine will see and how you can see what the compiler is doing to your code.

*For those interested the angle brackets are invalid tokens for a C# method but are valid MSIL tokens.  Hence why you see them here.  Along with a number of the other things that you might see in the compiler generated code.