.NET 接口上的静态构造函数未运行
您可以在 IL 中的 .NET 接口上定义静态构造函数。但是,如果这样做,当您在接口上运行方法时,静态构造函数不会运行:
.method public static void Main() {
.entrypoint
.locals init ( class IInterface cls1 )
// InterfaceClass static constructor is run
newobj instance void InterfaceClass::.ctor()
stloc.0
ldloc.0
// IInterface static constructor is not run!!!!!
callvirt instance int32 IInterface::Method()
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
.class public interface IInterface {
.method private static specialname rtspecialname void .cctor() {
ldstr "Interface static cctor"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
.method public abstract virtual instance int32 Method() {}
}
.class public InterfaceClass implements IInterface {
.method private static specialname rtspecialname void .cctor() {
ldstr "Class static cctor"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
.method public specialname rtspecialname instance void .ctor() {
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}
.method public virtual instance int32 Method() {
ldc.i4.s 42
ret
}
}
这是怎么回事? CLR 规范(分区 II,10.5.3.1)表示,类型初始值设定项何时执行是在分区 I 中指定的,但我在分区 I 中找不到任何对类型初始值设定项执行的引用。
编辑:
我可以运行接口静态初始化程序,但只能通过向接口添加静态字段并在代码中的某处访问该字段,即使该字段实际上并未在静态构造函数。因此,似乎在接口上调用方法不会使静态构造函数运行,但访问字段却可以。为什么会这样呢?规范中哪里提到了这一点?
You can define a static constructor on an interface in .NET in IL. However, if you do so, the static constructor is not run when you run a method on the interface:
.method public static void Main() {
.entrypoint
.locals init ( class IInterface cls1 )
// InterfaceClass static constructor is run
newobj instance void InterfaceClass::.ctor()
stloc.0
ldloc.0
// IInterface static constructor is not run!!!!!
callvirt instance int32 IInterface::Method()
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
.class public interface IInterface {
.method private static specialname rtspecialname void .cctor() {
ldstr "Interface static cctor"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
.method public abstract virtual instance int32 Method() {}
}
.class public InterfaceClass implements IInterface {
.method private static specialname rtspecialname void .cctor() {
ldstr "Class static cctor"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
.method public specialname rtspecialname instance void .ctor() {
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}
.method public virtual instance int32 Method() {
ldc.i4.s 42
ret
}
}
What's going on here? The CLR spec (Partition II, 10.5.3.1) says that when type initializers are executed is specified in Partition I, but I cannot find any reference in Partition I to type initializer execution.
EDIT:
I can get the interface static intitializer to run, but only by adding a static field to the interface, and accessing that field somewhere in the code, even if the field isn't actually assigned in the static constructor. So it seems that calling a method on an interface does not make the static constructor run, but accessing a field does. Why is this the case? And where is this mentioned in the spec?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在我看来,即使您可以在 CLI 中的接口上定义 .cctor,它也是无用的。第 I 部分第 8.9.5 条规定:
(强调我的)这意味着接口上的类型初始值设定项不会触发完全被自动调用。如果您希望调用它,您(恕我直言)需要在所有实现类中显式调用它,如下所示:
It seems to me that even though you can define a .cctor on an interface in CLI, it is kind of useless. Partition I, § 8.9.5 states:
(emphasis mine) Which means the type initializer on an interface does not get called automatically at all. If you want it to be called, you (IMHO) need to call it explicitly in all implementing classes, like this: