Quiz: Type Constructors


Clearly this code should fail a code review but what would calling PrintValue() display?

 

    public class Foo

    {

        public static int Value = 42;

        static Foo()

        {

            Value = 17;

        }

        public static void PrintValue ()

        {

            Console.WriteLine(Value);

        }

    }

 

Same, question, but in VB:

Class Foo

    Public Shared Value As Integer = 42

 

    Shared Sub New()

        Value = 17

    End Sub

 

    Public Shared Sub PrintValue()

        Console.WriteLine(Value)

    End Sub

 

End Class

 

Even more importantly, assuming we want Value to be initialized to 63, what is the best code and why?

 

Setting the static field in line:

    public class Foo

    {

        public static int Value = 63;

        public static void PrintValue ()

        {

            Console.WriteLine(Value);

        }

    }

 

Or using a type constructor:

    public class Foo

    {

        public static int Value;

        static Foo()

        {

            Value = 63;

        }

        public static void PrintValue ()

        {

            Console.WriteLine(Value);

        }

    }

 

Comments (15)

  1. ShadowChaser says:

    Not sure on #1 – I didn’t even know there were static constructors until now. 🙂

    For the second question, my guess is to initialize it where it is declared – I have a feeling the constructor may not be thread-safe, which is usually a requirement for static methods.

  2. RGabo says:

    Hey Brad,

    Wiling to guess first, thus its likely that i won’t be right but let’s try 😉

    First of all, the third snippet with the type constructor wouldn’t compile as you forgot to declare Value but that’s OK 😉

    Answer would be: It will write out 17. Although it might seem tricky as the IL code the line ‘public static int Value = 42’ will emit goes into .cctor (class constructor) too, the static member variable initialization takes place before the actual code in the class constructor.

    Basically:

    public static int Value = 42;

    static Foo()

    {

    Value = 17;

    }

    results in the same IL code as:

    public static int Value;

    static Foo()

    {

    Value = 42;

    Value = 17;

    }

    The second question seems a piece of cake from here as we already answered it. Both code snippets would result in the very same IL code, but I still think there must be a good reason to do one or the other.. Maybe the second makes more sense, because we won’t have IL code coming from two places in our source but one.. Can’t wait to hear which and why 😉

    RGabo

  3. Sean Chase says:

    1) 17 because the field initializer fires before the ctor.

    .

    2) "public static int Value = 63;" because you can be certain that Value will be initialized before anything else fires.

  4. Ben Monroe says:

    I think PrintValue() will print 17. The static field Value should be initialized first to 42 before the static constructor sets it to 17. Therefore, it is initially 42, but then immediately changed to 17 before any static members are called. (As a side note, a compiler warning might be useful to avoid such mistakes if there is not one yet.)

    As for the second question, I am unsure which is the "best" way. I suppose I would lean towards the static field line since it should be initialized prior to any initialization done in a static constructor.

  5. RGabo, thanks for pointing out the type-o in the last code snippet… fixed

  6. S N says:

    Declaring an explicit .cctor forces CLR Runtime to hook into all exposed members of the type during JIT while the first way of coding lets the CLR to hook in to only those static variables.

    So the first one is more JIT friendly than the second one.

  7. It’d have to be the field init code first, so that you could usefully access them in the type constructor. Suppose you had a static ArrayList = new … — and you used it from the type constructor, you’d expect it to be usable.

  8. RGabo says:

    cool.. first class gets IL keyword ‘beforefieldinit’ that the JITC will benefit from.. Makes sense!

  9. montaque says:

    public class Foo

    {

    public static int Value = 63;

    public static void PrintValue ()

    {

    Console.WriteLine(Value);

    }

    }

    is better

  10. Ming Chen(vsdata) says:

    For c#

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csspec/html/vclrfcsharpspec_10_11.asp

    17

    for vb

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbls7/html/vblrfvbspec7_2_2.asp

    17

    Setting static Field in line is better because you can call PrintValue function within the static constructor — that is the there is still possibility to making the mistake.

    That’s said, it is still not bullet proof — Look at the document for VB on shared constructor — the final example demo how thing can go wrong. It seems the most important keyword is "triggered" — if it ever get into recursive situation, VB compiler bail out by taking a "default" when recursive is detected. (That’s wht X is 1) For simple value initalized it should be O.K. — Just don’t get too crazy on setting static Field in line either. (not sure about C# compiler since the doc doesn’t talk about it at all…)

    -Ming

  11. David Levine says:

    For the 3rd question the only real difference I see is that the 1st definition of the class can be marked as BeforeFieldInit because it does not have a static constructor while the 2nd class definition cannot be so marked. This may change the timing as to when the field actually gets initialized to the value of 63; the runtime can be lazier as to when the field actually gets initialized when it is marked as BeforeFieldInit.

    In the 1st case I believe that it could conceivably initialize the field after the method PrintValue is invoked and immediately before the field is actually accessed. In the 2nd case the field would have to be initialized prior to invoking the method PrintValue.

    There may be a slight perf gain from not defining a static ctor, and the timing of when the field gets initialized can vary when marked BeforeFieldInit, but unless the code makes assumptions about when the field is initialized there should be little practical difference for the simple case here.

  12. Lawrence Pina says:

    By not using the initializer in line you might end up accessing the static before it was initialized.

    Ex.

    class Program

    {

    static void Main(string[] args)

    {

    Bar b = new Bar();

    Console.ReadLine();

    }

    }

    public class Foo

    {

    public static int Value;

    static Foo()

    {

    Bar b = new Bar(); //Will access static uninitialized

    Value = 63;

    }

    public static void PrintValue()

    {

    Console.WriteLine(Value);

    }

    }

    public class Bar:Foo

    {

    public Bar()

    {

    PrintValue();

    }

    }

  13. Kevin Westhead says:

    Out of curiosity, what is the reasoning behind the beforefieldinit behaviour? For example, why can’t I explicitly add this attribute to the type ctor? It seems to me that a type ctor is a fairly sensible place to perform intialisation of static members, and I could use the attribute to indicate whether or not I wanted lazy initialisation. Also, what are the scenarios where beforefieldinit is a bad idea, or in otherwords, why not always specify beforefieldinit for static members?

  14. Matthew W. Jackson says:

    Awww. I thought the quiz was going to be about co-dependent type constructors. There are lots of subtle bugs that can crop up if you have two type constructors that cause a circular initialization dependency. Due to the completely unexpected results, I really wish the compiler could warn you when you have a co-dependency.

    In my case it took my about 4 hours to figure out why some of my data was invalid.