静态参数的初始化顺序

Ava*_*lle 2 .net c# compiler-construction initialization

几周前,我从Java切换到C#.今天,我有一个奇怪的行为,我尝试在这个简单的样本中重现它.我正在使用.net FW 4.

我有三个类:第一个是抽象的:

namespace ReadonlyStaticOrder
{
    using System;
    using System.Collections.Generic;

    public abstract class AbstractClass
    {
        public AbstractClass(string value, IEnumerable<string> someValues)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            if (someValues == null)
            {
                throw new ArgumentNullException("someValues");
            }
            // would do something after...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

第二个 :

namespace ReadonlyStaticOrder
{
    using System.Collections.Generic;

    public sealed class ReadonlyOrderInitialization : AbstractClass
    {
        // this line introduces the bug, since it call the ctor before SomeValues already initialized
        // if removed, no more exception
        public static readonly ReadonlyOrderInitialization Sample = new ReadonlyOrderInitialization("sample");

        private static readonly IEnumerable<string> SomeValues = new string[] { "one", "two", "three" };

        public ReadonlyOrderInitialization(string value)
            : base(value, SomeValues)
        {
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

和示威者:

namespace ReadonlyStaticOrder
{
    using System;

    public sealed class Program
    {
        static void Main(string[] args)
        {
            try
            {
                new ReadonlyOrderInitialization("test");
            }
            catch (TypeInitializationException typeInitializationException)
            {
                Console.WriteLine(typeInitializationException.Message);
                Console.WriteLine(typeInitializationException.InnerException.Message);
                Console.WriteLine(typeInitializationException.StackTrace);
            }

            Console.ReadLine();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是:

'ReadonlyStaticOrder.ReadonlyOrderInitialization'的类型初始值设定项引发了异常.值不能为空.参数名:
readonlyStaticOrder.ReadonlyOrderInitialization..ctor (String value)中的someValues,位于d:\ stackoverflow\static readonlyissue\ConsoleApplication1\ReadonlyStaticOrder\Program.cs:第12行中的ReadonlyStaticOrder.Program.Main(String [] args)

我在引入错误的行上添加了评论.对我来说,编译器必须警告我,由于静态初始化的顺序,行为可能很奇怪.我错了吗?

谢谢你们,我希望你们有足够的信息.

Mar*_*ell 5

它被定义为文本顺序 - ECMA 334中的第17.11节:

如果一个类包含带有初始化程序的任何静态字段,那么这些初始化程序将在执行静态构造函数之前立即以文本顺序执行.

顺便说一句,如果你考虑,这会变得特别有趣partial classes,在这种情况下:它没有定义.

如果有疑问,请将初始化显式移动到静态构造函数.


至于为什么; 考虑(注意:这些只是我自己的想法):

  • "明确的任务"通常会阻止这是一个问题,但"明确的任务" 不适用于领域
  • 详细分析代码是计算复杂的(我想也许是"停顿") - 所以它只能提供一个不完整的安全贴面(这是人为的,并且可能导致任何非平凡场景中的问题)
  • 由于这个partial classes问题,完整的订单本身并没有严格定义; 所以它无法处理一般情况 - 再次,覆盖一个特定的情况(单个类片段等)回到"薄单板"(它只警告明显的情况,但无法帮助非平凡的情况)