views:

653

answers:

4

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  A: 

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.

Ray
Me doth thinks you did not readth the question.
Samuel
I read the question. Asking why C# does something one way, is never going to get you much of a useful answer. My reply was along the lines of, why would it when you can do this...
Ray
Asking why something works in C# has worked a lot of times; just look at how much Jon Skeet knows about the mechanics of C#.
Samuel
It's better to use initialisation methods, FXCop will tell you this.
AdamRalph
Regardless of what FXCop tells you, this does not answer the question.
Samuel
Yes but what's the point? It's not going to change. Also I had an answer to why before your down vote, and the other answer doesn't say why either.
Ray
I know exactly how to fix the problem. I am looking for exactly what I asked for.
BCS
@AdamRalph: My FXCop does not tell me this...@Ray: Static constructors do not have access modifiers because they are runned anyway.
Paco
A: 

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.

James Schek
I asked that question :b Also see my comment to Ray. I'm /not/ asking how to fix that code.
BCS
Yeah, you did. :-) I guess I should pay more attention!
James Schek
"'Something is wrong, please contact the sys admin', Crud! I would but I /am/ the sys admin!" <g/>
BCS
+10  A: 

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:

Krzysztof Koźmic
That's the primary reason: initialization cycles that the compiler can't resolve.
Jim Mischel
Cycles are always an error: I'd rather get compiler errors than what you currently get. Aside from cycles, I see no issues. +1
BCS
+2  A: 

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.

Jim Mischel
A good point and it might be the reason. That said I think that the "evaluate in order" way is wrong the way to solve that. I think the correct tact is to say, "if order matters, initialize in a constructor." and "Code that depends on order of inline initialization is illegal, even if it runs".
BCS