Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么静态构造函数没有首先调用,而我在使用声明的变量时遇到异常?_C#_.net_Dictionary_Constructor_Static Constructor - Fatal编程技术网

C# 为什么静态构造函数没有首先调用,而我在使用声明的变量时遇到异常?

C# 为什么静态构造函数没有首先调用,而我在使用声明的变量时遇到异常?,c#,.net,dictionary,constructor,static-constructor,C#,.net,Dictionary,Constructor,Static Constructor,来自MSDN 静态构造函数用于初始化任何静态数据,或执行只需执行一次的特定操作。在创建第一个实例或引用任何静态成员之前,会自动调用它 现在我的问题来了: public static class DateFormat { private static List<string> DateFormats = new List<string>(); public static string DateSeparator { get; set; } = "

来自MSDN


静态构造函数用于初始化任何静态数据,或执行只需执行一次的特定操作。在创建第一个实例或引用任何静态成员之前,会自动调用它

现在我的问题来了:

public static class DateFormat
{
    private static List<string> DateFormats = new List<string>();

    public static string DateSeparator  { get; set; } = "/";

    public static string Current { get; set; } = DateFormats[1]; // error here

    static DateFormat()
    {
        DateFormats.Add("yyyy{0}MM{0}dd HH{1}mm{1}ss");
        DateFormats.Add("yyyy{0}MM{0}dd hh{1}mm{1}ss");
    }
}
如上所述,调用DateFormats[1]时出现错误

“DateFormat”的类型初始值设定项引发异常


构造函数是否应该首先调用静态构造函数?因此,字典将被填充,然后对使用它的变量的任何调用都将正常。

此行为记录在此处:

具体而言,本节:

如果静态字段变量初始值设定项存在于静态构造函数的类中,则它们将按照文本顺序执行,在执行静态构造函数之前,它们会立即出现在类声明中

由于静态字段变量初始值设定项确实存在,它们将在静态构造函数之前进行初始化,这就是您看到错误的原因:

public static string Current { get; set; } = DateFormats[1]; 
将在

static DateFormat()
{
    DateFormats.Add("yyyy{0}MM{0}dd HH{1}mm{1}ss");
    DateFormats.Add("yyyy{0}MM{0}dd hh{1}mm{1}ss");
}
当然,DateFormats列表在执行DateFormats[1]时仍然是空的

要解决此问题,只需在静态构造函数中初始化Current:

public static class DateFormat
{
    static DateFormat()
    {
        DateFormats.Add("yyyy{0}MM{0}dd HH{1}mm{1}ss");
        DateFormats.Add("yyyy{0}MM{0}dd hh{1}mm{1}ss");

        Current = DateFormats[1];
    }

    private static List<string> DateFormats = new List<string>();

    public static string DateSeparator { get; set; } = "/";

    public static string Current { get; set; }
}

这就是所有语法糖的翻译方式:

static DateFormat()
{
    DateFormats = new List<string>();
    DateSeparator = "/";
    Current = DateFormats[1]; // at this point DateFormats is empty
    DateFormats.Add("yyyy{0}MM{0}dd HH{1}mm{1}ss");
    DateFormats.Add("yyyy{0}MM{0}dd hh{1}mm{1}ss");
}
不要在构造函数中混合内联初始化和代码。头痛。
尤其是当班级成员相互依赖时。对于实例构造函数也是如此。

静态构造函数用于初始化任何静态数据!!首先初始化,然后填充。请参阅上面的mSDN。它说静态构造函数是先调用的。请注意,您也可以内联初始化该列表,而不使用构造函数。是的,它说的是,它发生的是它确切说的。它叫“第一”,我现在知道了。但是静态构造函数没有首先调用。我做错什么了吗?@asdk1200000:混合初始值设定项和构造函数的任何问题的解决方案都很简单:不要混合它们。而是在构造函数中编写所有内容。在后台,编译器无论如何都必须将所有初始值设定项代码移动到构造函数中,因此您最好对此进行明确说明。因此,如果存在初始值设定项,则静态构造函数将永远不会首先命中?这是吗true@asdk1200000:在IL级别上,初始值设定项不存在。编译器接受初始值设定项和您在静态构造函数中编写的任何内容,并将它们排列到一个构造函数体中,初始值设定项以文本顺序出现,然后是您显式放入构造函数体中的任何内容。虽然这些都是有文档记录和可预测的,但依赖它只会使代码变得脆弱和难以理解。一旦你有太复杂的事情需要单独为初始值设定者处理,你最好把所有的东西都显式地移到构造函数中,这样就可以清楚地知道发生了什么。但是,当我去处理一些我需要知道的事情时。。因为这是我有生以来第一次使用静态构造函数。所以,如果只有一个静态字段初始化了静态构造函数,那么静态构造函数不会首先被调用?或者如果初始化了未调用的静态constructor,则将调用的字段@asdk1200000它完全按照我引用的文档中描述的顺序发生。我不知道如何详细说明这一点;这一点非常清楚:所有静态字段(如果有)都将在静态构造函数之前进行初始化,按照它们在代码文件中出现的顺序进行初始化。