Is the “textual order” across partial classes form

2019-01-11 12:19发布

问题:

Specifically, in relation to field initializers (in this case, static) - §17.11 in ECMA 334:

If a class contains any static fields with initializers, those initializers are executed in textual order immediately prior to executing the static constructor.

Now, if we have multiple partial classes in separate files, is that order determined anywhere? My gut says "not formally defined, but probably relates to the order included in the csproj, or the order noted to csc". Is this correct?

(and yes, I realise it would be better to avoid the ambiguity completely - probably by moving all the initialization to a static constructor).


For example, if I have a.cs:

using System;
partial class Program
{
    private static int Foo = Write("Foo");
    static int Write(string name)
    {
        Console.WriteLine(name);
        return 0;
    }
    static void Main()
    {
        Console.WriteLine("[press any key]");
        Console.ReadLine();
    }
}

and b.cs:

partial class Program
{
    private static int Bar = Write("Bar");
}

and:

<Compile Include="a.cs" />
<Compile Include="b.cs" />

then this is Foo then Bar; if, however, this is:

<Compile Include="b.cs" />
<Compile Include="a.cs" />

then it is Bar then Foo. This supports the observation, but does not state it strongly. §8.7.13 (Partial type declarations) makes no comment on the order when combining partial classes. So; is there anything stronger we can say here, either from the C# language spec or from the tooling documentation?

Additionally, it behaves similarly with csc a.cs b.cs vs csc b.cs a.cs.

回答1:

Here's another snippet from the C# spec which, taken with your snippet, appears to settle that this is undefined behaviour:

10.2.6 Members

[...] The ordering of members within a type is rarely significant to C# code, but may be significant when interfacing with other languages and environments. In these cases, the ordering of members within a type declared in multiple parts is undefined.

To be fair, it does say rarely significant, not insignificant :).



回答2:

I know this question is very old, but here is the correct part of the specification:

ECMA-334 (C# Language Specification), Variable initializers, section 17.4.5:

When there are field declarations in multiple partial type declarations for the same type, the order of the parts is unspecified. However, within each part the field initializers are executed in order.

So the "textual order" in partial types is not undefined, rather it's partially defined. ;-)