Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why in C# does order matter for static initialization?

This code has the well defined behavior in C# of not working:

class Foo
{
    static List<int> to = new List<int>( from ); // from is still null
    static IEnumerable<int> from = Something();
}

Note: I'm not asking how to fix that code as I already known how to do that

What is the justification for this? C# already does run time checks to detect the first access to static members. Why not extend this to a per member thing and have them run on demand or even better have the compiler figure out the order at compile time?

BTW: I think the same question (or almost the same) also holds for non static members.

like image 681
BCS Avatar asked Mar 18 '09 21:03

BCS


4 Answers

Initializers are just a syntactic sugar. Compiler puts that code in the .cctor when it compiles your class, and it pust them in the orders they're layed out in the code.

It doesn't run any checks, because it wouldn't make sense. You could still have initialization cycles, so it wouldn't work anyway.

I blogged about it some time ago if you're interested:

  • more on inline initialization
  • more on inline initialization (answer)
like image 181
Krzysztof Kozmic Avatar answered Oct 06 '22 19:10

Krzysztof Kozmic


I can envision a programmer depending on initialization order due to side effects with other static classes. You and I both know that depending on side effects is bad practice, but it's not necessarily illegal.

Consider something like this:

class Foo
{
    static string header = Bar.GetHeader();
    static string version = Bar.GetVersion();
}

And Bar.GetVersion assumes that Bar.GetHeader has been called. If the compiler were free to change the initialization order, then the programmer wouldn't be able to guarantee the initialization order.

Ugly, granted, but perfectly legal. If you imagine second-order effects (i.e. called static methods that themselves depend on classes that have side effects), you see that it's impossible for the compiler to reliably rearrange anything, just as it's impossible (in general) for the compiler to rearrange the order of function calls in your static constructor.

like image 38
Jim Mischel Avatar answered Oct 06 '22 19:10

Jim Mischel


C# does runtime checks to detect the first access to a class, but does not re-order static initialization within a class.

The static fields are initialized from top to bottom followed by the static constructors from top to bottom. Either change the order of your fields or create a static constructor and initialize the fields from tehre.

See Variable initializers in the C# spec or this article on initializers.. Also, the question Order of static constructors/initializers in C# is related.

like image 36
James Schek Avatar answered Oct 06 '22 20:10

James Schek


I think what you need to use is a static constructor.

Like so

class Foo
{
    static List<int> to;
    static IEnumerable<int> from;

    static Foo()
    {
        from = Something();
        to = new List<int>(from);
    }
}

As to why C# doesn't do it on first access, I just don't see the need for that kind of complexity when there are other alternatives that make it clear what's happening.

like image 27
Ray Avatar answered Oct 06 '22 19:10

Ray