Reputation: 438
This sample from C# in a Nutshell says it writes 0 followed by 3 due to "the field initializer that instantiates a Foo executes before X is initialized to 3".
class Program {
static void Main() { Console.WriteLine (Foo.X); } // 3
}
class Foo
{
public static Foo Instance = new Foo(); //static field 1
public static int X = 3; //static field 2
Foo() => Console.WriteLine (X); // 0
}
My question is, why does this not go into an infinite recursion due to static field 1 which makes a new Foo (which makes a new Foo, which makes a new Foo, etc.)?
Upvotes: 0
Views: 99
Reputation: 186668
Let's have a look at what's going on. BeforeFoo
class addressing static
fields must be
initialized.
class Program {
static void Main() {
// Before Foo class is addressed (here Foo.X), Foo must be initialized
Console.WriteLine(Foo.X);
}
}
.Net will do it in order they are mentioned in the class declaration:
class Foo
{
// Will be run first
public static Foo Instance = new Foo();
// Will be run second
public static int X = 3;
Foo() => Console.WriteLine(X);
}
Instance
start its initializationpublic static Foo Instance = new Foo();
constructor Foo()
called which prints X
: Foo() => Console.WriteLine (X);
note,
that since X
has not been initialized, 0
will be printed.
X
will be initialized, it's now 3
Initialization is completed now, and .Net is ready to adddress Foo
class
Console.WriteLine(Foo.X);
and 3
will be printed (note the 2nd step of the initialization)
Upvotes: 1
Reputation: 3414
Static fields and properties are shared across all instances of a class, and get initialized in a special constructor called .cctor
that gets called when the class is first referenced.
So the compiled code is something similar to
class Foo
{
public static Foo Instance;
public static int X;
.cctor() {
Instance = new Foo();
X = 3;
}
Foo() => Console.WriteLine (X);
}
The call flow would be Foo::.cctor
-> Foo::Foo()
-> Foo:get_X()
.
So there is no recursion, but X
will have its default value when .cctor
is called.
Upvotes: 1