嵌套静态类在其父级之前初始化似乎存在问题。请参阅下面的示例,我添加了注释,以指示我期望事物初始化/调用的顺序以及实际的顺序。在这种情况下,我正在调用Test1.Test2.GetName()
,所以我希望按以下顺序初始化静态类:Test1
,Test2
using System;
using System.Collections.Generic;
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
Console.WriteLine(Test1.Test2.GetName());
Console.ReadKey();
}
}
public static class Test1 {
// Actual Order: 2; Expected: 1
private static string Name = "Test1";
public static List<string> Names { get; private set; }
// Actual Order: 3; Expected: 2
static Test1() {
Test1.Names = new List<string>(new string[] {
Test2.GetName()
});
}
public static class Test2 {
// Actual Order: 1; Expected: 3
private static string Name = Test1.Name.ToString() + "_Test2";
// Actual Order: 4; Expected: 4
public static string GetName() {
return Name.ToString();
}
}
}
}
我认为静态是在第一次触摸类时初始化的,但显然触及嵌套类并不首先初始化父级!这对我来说就像一个错误。它正在这样做:
Test2.Name
- &gt; Test1.Name
- &gt; Test1()
- &gt; Test2.GetName()
- &gt; Test2.Name
因此虽然Test2.Name
是切入点,但理论上它并不是在需要的时候初始化的。
答案 0 :(得分:4)
在创建第一个实例或引用任何静态成员之前,会自动调用静态构造函数来初始化类。
问题是嵌套类不是其父级的静态成员。它完全是一个不同的阶级。它有一个nested
attribute,但这仅用于会员可见性。
来自ECMA-335(CLI规范):
I.8.11.5嵌套类型定义
嵌套类型定义与顶级类型定义相同,但有一个例外:顶级 type具有visibility属性,而嵌套类型的可见性与可见性相同 封闭式。
因此,行为是正确的。在调用嵌套类时,文档不需要初始化父类。无论如何,您应该注意应该避免使用嵌套的公共类,就像公共字段一样,因为这不是很好的封装。嵌套类应主要用于实现细节,并从外部隐藏。
如果嵌套类要求首先初始化其父类,则可以在其静态构造函数中显式强制它:
static Test2()
{
RuntimeHelpers.RunClassConstructor(typeof(Test1).TypeHandle);
}
这里的含义非常明确。
但这不会使你的例子有效,因为它有一个循环依赖:
Test1
静态构造函数调用Test2.GetName()
,这意味着它将触发Test2
的初始化Test2
静态构造函数(隐式)调用Test1.Name.ToString() + "_Test2"
,这将触发Test1
的初始化无论哪种方式,它都不会起作用,你必须修复该代码。