Fun fact: C# methods whose bodies span over multiple source files 4

Posted by Jb Evain Thu, 19 Jan 2012 21:00:00 GMT

While working on Mono.Cecil (your lovely library to analyze and manipulate .net binaries that is used by legions), one thing that struck me as odd for a while, was the fact that a method could have debug symbols for instructions that are defined in multiple files.

Cecil has this type, Instruction. When you’re analyzing a module with debug information (think .pdb or .mdb files), an Instruction may have its SequencePoint property set. A sequence point is nothing but the location of the code in a file that relates to the instruction.

What got me wondering, is that the APIs to retrieve those sequence points make it so that a method can have sequence points in different documents. So be it, this is how I ended up representing it in Cecil, but it’s only recently that I stumbled upon a case where indeed, a C# method had instructions defined in multiple files:

Foo.Bar.cs:
public partial class Foo {
    private List<Bar> _bars = new List<Bar>();
}

Foo.Baz.cs:

public partial class Foo {
    private Baz _baz;

    public Foo (Baz baz)
    {
        _baz = baz;
    }
}

Do you see what’s going on here?

The constructor of Foo is defined in Foo.Baz.cs, but there’s a field initializer in Foo.Bar.cs that is going to be compiled inside Foo’s constructor. When you debug the constructor, you’ll effectively end up jumping between the two files. Crazy right?

Can you think of another case where a C# (or VB.NET for that matters) method would have instructions defined in different files?

Trackbacks

Use the following link to trackback from your own site:
http://www.evain.net/blog/articles/trackback/817

Comments

Leave a response

  1. Avatar
    Patrick Smacchia Fri, 20 Jan 2012 10:47:16 GMT

    Indeed, I stumbled on this particular case of field initialization in ctor, it does happen as well for the static ctor and static fields. And in VS you can put a breakpoint on the field init :)

  2. Avatar
    Joe White Fri, 20 Jan 2012 13:16:56 GMT

    I was puzzled when I read the title. I figured it had to have something to do with partial classes, but I couldn’t figure out what else—partial methods didn’t fit. But the moment I read the field declaration, the light bulb went on. Sneaky! It’s even a source location that could show up multiple times (once per constructor), which means there isn’t a one-to-one mapping from source locations to methods.

    And no, I can’t think of anywhere else that would happen. Field initializers are kind of an edge case, since the order isn’t supposed to matter; I can’t think of anything else in C# where order wouldn’t matter in putting code fragments together into a method. Why, do you know of another way?

  3. Avatar
    Uwe Thomas Sat, 21 Jan 2012 11:10:45 GMT

    something similar can occur for generated C# code: A code generator could add #line directives to the code which redefines the source line and also the file name for the sequence points. This way parts of a C# method might be located in an XML file of YACC grammar.

  4. Avatar
    Jb Evain Sun, 22 Jan 2012 17:16:33 GMT

    Uwe: excellent observation!

Comments