Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fields Initilizers (Static or not) and Constructor (Static or not) which one runs first

Something is not clear to me, according to what I read:

  1. Field Initializers run before Constructors.
  2. Static field Initializers execute before the static constructor is called (which is still compatible with point 1.).
  3. If a type has no static constructor, field Initializers will execute before the type being used (as I understand : not being instantiated but rather being used)

This example explains :

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Foo.X);
        Console.ReadLine();
    }
}

class Foo
{
    public static Foo Instance = new Foo();
    public static int X = 3;

    Foo()
    {
        Console.WriteLine("In constructor: " + X);
    }
}

This Code Prints 0, then 3 ! How could that be possible? When we use Foo by doing Foo.X the two first initializers are called, before the constructor (that's ok so far), when

public static Foo Instance = new Foo();

is executed it should run its own 2 initializers before calling the constructor (Point 1) whereas it runs the constructor first and prints X with 0 as a default value.

I can't really follow the logic on this, please clarify to me.

Edit : what I expect to happen :

  1. when Foo.X : execute: public static Foo Instance = new Foo();
  2. before calling the constructor that prints ("In constructor: " + X), public static int X = 3; should be executed, but it happens that the constructor fires first, isn't supposed that the fields complete running first ? I mean even when jumping inside creating a new Foo instance fields must be run first.
  3. From the two last points I expect to print 3 then 3
like image 774
AymenDaoudi Avatar asked Feb 02 '14 18:02

AymenDaoudi


1 Answers

If a type has no static constructor, field Initializers will execute before the type being used (as I understand : not being instantiated but rather being used)

Not necessarily.

If there is no static constructor, then static field initializers will be executed at some time before a static field is first used - but the static field initializers don't have to execute before any instances are created.

From the C# 5 specification section 10.5.5.1:

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 (§10.12) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class.

But in your case, you're just seeing that when the constructor of Foo is called in order to initialize Instance, X is still 0, because it hasn't been assigned a value. The field initializers are executed in textual order, so Instance is assigned a value before X. It's as simple as that - it's not a matter of timing between static fields and instance fields, as you haven't got any instance fields.

EDIT: It seems that you're being getting confused by the constructor call. Foo is already being initialized - the constructor call doesn't change that, and there's no "second initialization". The constructor is called normally, prints "0" and then returns. Then X is assigned a value of 3.

like image 145
Jon Skeet Avatar answered Sep 17 '22 19:09

Jon Skeet