静态参数的初始化顺序 [英] Order of initialization of static parameters

查看:97
本文介绍了静态参数的初始化顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Few weeks ago, I switched from Java to C#. Today, I had a weird behavior and I try to reproduce it in this simple sample. I'm using a .net FW 4.

我有3个类:
首先,抽象类:

I have three classes: First, the abstract one:

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...
        }
    }
}

第二个:

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)
        {
        }
    }
}

演示者:

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();
        }
    }
}

输出为:



'ReadonlyStaticOrder.ReadonlyOrderInitialization'的类型初始值设定项引发了异常。
值不能为null。参数名称:
处的someValues ReadonlyStaticOrder.ReadonlyOrderInitialization..ctor(String value)

在$ only $ Status.Program.Main(String [] args)中位于
d中:
readonlyissue\ConsoleApplication1\ReadonlyStaticOrder\Program.cs:line
12

The type initializer for 'ReadonlyStaticOrder.ReadonlyOrderInitialization' threw an exception. Value cannot be null. Parameter name: someValues at ReadonlyStaticOrder.ReadonlyOrderInitialization..ctor(String value)
at ReadonlyStaticOrder.Program.Main(String[] args) in d:\stackoverflow\static readonlyissue\ConsoleApplication1\ReadonlyStaticOrder\Program.cs:line 12

我添加了一条评论在介绍错误的那一行。对我来说,编译器将不得不警告我,由于静态初始化的顺序,该行为可能很奇怪。我错了吗?

I added a comment on the line which introduces the bug. For me, the compiler would have to warn me that the behavior can be weird because of the order of static initialization. Am I wrong?

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

Thank you guys and I hope you have enough information.

推荐答案

定义为为文本顺序-ECMA 334中的§17.11:

It is defined as text order - §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.

另外,这包含带有初始化程序的任何静态字段,这些初始化程序将在执行静态构造函数之前按文本顺序执行。如果考虑使用部分类特别会很有趣,

As an aside, this gets particularly interesting if you consider partial classes, in which case : it is not defined.

如有疑问,请移动初始化

If in doubt, move the initialization explicitly to a static constructor.

为什么?考虑一下(注意:这些只是我自己的想法):

As for why; consider (note: these are just my own thoughts):


  • 确定的分配通常可以避免这是一个问题,但是确定分配 不适用于字段

  • 详细分析代码在计算上很复杂(我正在考虑暂停)-因此只能提供不完整的安全饰面(这是人为的,在任何不平凡的情况下都可能导致问题)

  • 并且由于部分等级问题,本身的完整订单没有严格定义;因此,它无法处理一般情况-再次,覆盖特定于 的情况(单个类片段等)又回到了薄贴面(此处仅针对明显的情况,但对于不重要的情况却无济于事)

  • "definite assignment" is the thing that usually stops this being an issue, but "definite assignment" does not apply to fields
  • analysing the code in full detail is computationally complex (I'm thinking "halting", perhaps) - so it could only offer an incomplete veneer of safety (which is artificial and could lead to problems in any non-trivial scenario)
  • and due to the partial classes issue, the full order itself is not strictly defined; so it cannot handle the general case - and again, covering a specific case (single class fragment etc) is back to the "thin veneer" (where it only warns for the obvious cases, but can't help with the non-trivial ones)

这篇关于静态参数的初始化顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆