在 ECMA standard在 $14.5.6.2 下,它指出静态构造函数会影响静态字段初始化顺序。我想要一种方法来强制执行此操作,但无法找到一种方法来检查类型中的显式静态构造函数。如果还没有(并且该类有一些静态字段),C# 运行时似乎会自动生成一个。 是否可以使用反射检查类是否具有显式静态构造函数?
例如 - 下面将在这两种情况下返回一个构造函数,并且我看不出它们之间有任何区别:
static class NoStaticConstructor
{
public static string Field = "x";
}
static class HasStaticConstructor
{
static HasStaticConstructor() {}
}
public void Test()
{
typeof(NoStaticConstructor)
.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic)
.ShouldBeEmpty(); // FAILS
typeof(HasStaticConstructor)
.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic)
.ShouldNotBeEmpty(); // SUCCEEDS
}
最佳答案
如果你看generated IL对于这两个类,您将看到它们都有一个静态构造函数:
.method private hidebysig specialname rtspecialname static
void .cctor () cil managed
{ /*...*/ } // end of method HasStaticConstructor::.cctor
.method private hidebysig specialname rtspecialname static
void .cctor () cil managed
{ /*...*/ } // end of method NoStaticConstructor::.cctor
因此,查询构造函数不会对您有帮助,因为无论它是否在 C# 代码中显式编写,它都存在于已编译的代码中。
好消息是,实际上不需要检查构造函数。相反,您应该查找 TypeAttributes.BeforeFieldInit
。如前所述here ,默认情况下应用 beforefieldinit
标志,除非该类具有静态构造函数。 这为您提供了您正在寻找的有关静态字段初始化顺序的信息。
我们可以编写一个辅助方法来检查:
static bool HasLazyInitialization(Type t) =>
t.Attributes.HasFlag(TypeAttributes.BeforeFieldInit);
用法:
Console.WriteLine(HasLazyInitialization(typeof(NoStaticConstructor))); // true.
Console.WriteLine(HasLazyInitialization(typeof(HasStaticConstructor))); // false.
关于c# - 检查一个类是否有显式静态构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74134653/