不运行.NET接口上的静态构造函数

the*_*oop 10 .net interface static-constructor intermediate-language

您可以在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
    }
}
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?CLR规范(分区II,10.5.3.1)说,当在分区I中指定执行类型初始值设定项时,但我在分区I中找不到任何类型初始化程序执行的引用.

编辑:

可以让接口static intitializer运行,但只能通过向接口添加静态字段,并在代码中的某个位置访问该字段,即使该字段实际上没有在静态构造函数中分配.因此,似乎在接口上调用方法不会使静态构造函数运行,但访问字段会起作用.为什么会这样?规范中提到了哪里?

Mor*_*gil 10

似乎对我来说,即使你可以在命令行接口上定义.cctor,它是一种无用的.分区I,§8.9.5规定:

如果标记为BeforeFieldInit,则类型的初始化方法在首次访问为该类型定义的任何静态字段时或之前执行.如果未标记为BeforeFieldInit,则执行该类型的初始化方法(即,由其触发):首先访问该类型的任何静态字段,或者首先调用该类型的任何静态方法,或者首先调用任何实例或虚方法如果它是值类型或第一次调用该类型的任何构造函数,则为该类型的. 执行任何类型的初始化方法都不会触发自动执行由其基类型定义的任何初始化方法,也不会触发该类型实现的任何接口的自动执行

(强调我的)这意味着接口上的类型初始化器根本不会被自动调用.如果你想要它被调用,你(恕我直言)需要在所有实现类中显式调用它,如下所示:

.method private static specialname rtspecialname void .cctor() {
    ldtoken IInterface
    callvirt instance valuetype [mscorlib]System.RuntimeTypeHandle [mscorlib]System.Type::get_TypeHandle()
    call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::RunClassConstructor(valuetype [mscorlib]System.RuntimeTypeHandle)
    ldstr "Class static cctor"
    call void [mscorlib]System.Console::WriteLine(string)
    ret
}
Run Code Online (Sandbox Code Playgroud)