Order of static constructors/initializers in C#

后端 未结 4 1432
梦如初夏
梦如初夏 2020-12-03 10:02

While working on a C# app I just noticed that in several places static initializers have dependencies on each other like this:

static private List         


        
4条回答
  •  失恋的感觉
    2020-12-03 10:56

    It seems to depend on the sequence of lines. This code works:

    static private List a = new List() { 1 };
    static private List b = new List() { a[0] };
    

    while this code does not work (it throws a NullReferenceException)

    static private List a = new List() { b[0] };
    static private List b = new List() { 1 };
    

    So, obviously no rules for cyclical dependency exist. It's peculiar however that the compiler does not complain...


    EDIT - What's happening "across files"? If we declare these two classes:

    public class A {
        public static List a = new List() { B.b[0] };
    }
    public class B {
        public static List b = new List() { A.a[0] };
    }
    

    and try to access them with this code:

    try { Console.WriteLine(B.b); } catch (Exception e) { Console.WriteLine(e.InnerException.Message.); }
    try { Console.WriteLine(A.a); } catch (Exception e) { Console.WriteLine(e.InnerException.Message); }
    try { Console.WriteLine(B.b); } catch (Exception e) { Console.WriteLine(e.InnerException.Message); }
    

    we are getting this output:

    The type initializer for 'A' threw an exception.
    Object reference not set to an instance of an object.
    The type initializer for 'A' threw an exception.
    

    So the initialization of B causes an exception in static constructor A and lefts field a with the default value (null). Since a is null, b can not also be initialized properly.

    If we do not have cyclical dependencies, everything works fine.


    EDIT: Just in case you didn't read the comments, Jon Skeet provides a very interesting reading: The differences between static constructors and type initializers.

提交回复
热议问题