Why in C# does order matter for static initialization?

爷,独闯天下 提交于 2020-01-02 02:51:51

问题


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.


回答1:


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.




回答2:


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)



回答3:


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.




回答4:


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.



来源:https://stackoverflow.com/questions/660197/why-in-c-sharp-does-order-matter-for-static-initialization

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!