I've been through the relevant section of C# Language Spec (v5.0) but I can't find the piece that's relevant to what I'm seeing.
If you have a run of the code below, you'll see the output below, which is what I expect:
using System;
class Test {
static int count = 0;
static void Main() {
Console.WriteLine("In Main(), A.X=" + A.X);
}
public static int F(string message) {
Console.WriteLine(message);
A.X = ++count;
Console.WriteLine("\tA.X has been set to " + A.X);
B.Y = ++count;
Console.WriteLine("\tB.Y has been set to " + B.Y);
return 999;
}
}
class A {
static A() { }
public static int U = Test.F("Init A.U");
public static int X = Test.F("Init A.X");
}
class B {
static B() { }
public static int R = Test.F("Init B.R");
public static int Y = Test.F("Init B.Y");
}
The output is:
Init A.U
A.X has been set to 1
Init B.R
A.X has been set to 3
B.Y has been set to 4
Init B.Y
A.X has been set to 5
B.Y has been set to 6
B.Y has been set to 2
Init A.X
A.X has been set to 7
B.Y has been set to 8
In Main(), A.X=999
This is exactly the output I'd expect. In particular, notice that even though method F() is executing with the parameter, "Init A.U", it is called again (interrupted, if you like) once the reference to B.Y is encountered, causing B's static initializers to execute. Once B's static constructor completes, we return again to the A.U invocation of F(), which accounts for B.Y being set to 6 and then to 2. So, hopefully this output makes sense to everyone.
Here's what I'm not understanding: If you comment out B's static constructor, this is the output you see:
Init B.R
A.X has been set to 1
B.Y has been set to 2
Init B.Y
A.X has been set to 3
B.Y has been set to 4
Init A.U
A.X has been set to 5
B.Y has been set to 6
Init A.X
A.X has been set to 7
B.Y has been set to 8
In Main(), A.X=999
Sections 10.5.5.1 and 10.12 of the C# Spec (v5.0) indicate A's static constructor (and its static initializers) are triggered to execute when "any of the static members of the class are referenced." Yet here we have A.X referenced from within F() and A's static constructor is not triggered (since its static initializers are not running).
Since A has a static constructor I would expect those initializers to run (and interrupt) the "Init B.R" call to F(), just as B's static constructor interrupted A's call to F() in the "Init A.U" call that I showed at the beginning.
Can anyone explain? Af face value it looks like a violation of the spec, unless there's some other part of the spec that allows this.
Thanks