20

Dear all, the question like this one has been already asked, but among the answers there was no explanation of the problem which I see.

The problem: the C# Programming Guide says:

A static constructor is used to initialize any static data, or to perform a particular action that needs performed once only. It is called automatically before the first instance is created or any static members are referenced.

In particular, static constructor is called before any instance of a class is created. (This doesn't ensure that the static constructor finishes before creation of instance, but this is a different story.)

Let's consider the example code:

using System;

public class Test
{
    static public Test test = new Test();
    static Test()
    {
        Console.WriteLine("static Test()");
    }
    public Test()
    {
        Console.WriteLine("new Test()");
    }
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Main() started");
        Console.WriteLine("Test.test = " + Test.test);
        Console.WriteLine("Main() finished");
    }
}

It outputs:

Main() started
new Test()
static Test()
Test.test = Test
Main() finished

So we can see that the instance constructor finishes (and thus an instance is created) before the static constructor starts. Doesn't this contradict the Guide? Maybe the initialization of static fields is considered to be an implicit part of static constructor?

7
  • 1
    Why don't you actually instantiate it outside of the class versus assigning an instance to a static property, then check the order? This looks like a funky way to test it to me. Commented Nov 10, 2010 at 23:38
  • 1
    Isn't that because you're instantiating a static member...? Commented Nov 10, 2010 at 23:40
  • @mway: it may work other way, but I would like to understand what happens in exactly this case. Commented Nov 10, 2010 at 23:42
  • 1
    @SLaks: If I would design the language, I would expect this code to be not compileable, frankly speaking. I know that the dependencies may be indirect and therefore not resolvable at compile time, so I would expect at least a runtime error in this case, in order to guarantee that the static constructor is finished strictly prior to any instance constructors. Commented Nov 10, 2010 at 23:49
  • My question asked in order to understand what is going on in stackoverflow.com/questions/4148169/… Commented Nov 10, 2010 at 23:52

1 Answer 1

30

Inline initializers for static fields run before the explicit static constructor.

The compiler transforms your class into something like this:

public class Test {
    .cctor {    //Class constructor
        Test.test = new Test();                //Inline field initializer
        Console.WriteLine("static Test()");    //Explicit static ctor
    }
    .ctor { ... }    //Instance constructor
}

Note that this is independent of the declaration order.

To quote the spec:

The static field variable initializers of a class correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration. If a static constructor (Section 10.11) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor.

Sign up to request clarification or add additional context in comments.

20 Comments

Yes, this is guaranteed by msdn.microsoft.com/en-us/library/79b3xss3.aspx: "Static members are initialized before the static member is accessed for the first time and before the static constructor, if there is one, is called." But doesn't this contradict the first citation from the question?
@Vlad: If the static ctor instantiates the class, it will not finish until it instantiates the class.
@Vlad: The field initializers become part of the IL .cctor method. They aren't part of the explicitly declared static constructor, but they all get compiled into the same .cctor. Your maybe (at the end of the question) is correct.
@Vlad: C# treats field initializers and static constructor as two separate concepts. However, .NET has only one: the type initializer, which carries the special name .cctor. The C# compiler places both field initializers and static constructor into the .NET type initializer for the class. .NET guarantees that the type initializer begins running before any instance constructor, and this holds true in your example. When the C# spec tries to separate it into two concepts, it becomes inconsistent. The actual behavior is governed by the CLR spec.
@Vlad: Yes, the Guide is wrong. It introduces a paradox. Static constructor before instance constructor. Field initializer before static constructor. Instance constructor in the field initializer. @LukeH: That's a very good point, and one I've run into before in C++/CLI. Actually, my comment is perfectly accurate about what the guarantee made by .NET is, but that guarantee only applied to types without beforefieldinit, as you correctly point out. A C# class with a C# static constructor is never marked beforefieldinit, so the alternate guarantee is not interesting for C#.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.