Статический конструктор в .NET-интерфейсе не запускается - PullRequest
10 голосов
/ 14 марта 2011

Вы можете определить статический конструктор на интерфейсе в .NET в IL.Однако, если вы это сделаете, статический конструктор не будет запущен при запуске метода в интерфейсе:

.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 на выполнение инициализатора типов.

EDIT:

I может запустить статический интерфейс инициализации интерфейса, но только путем добавления статического поля к интерфейсу и доступа к этому полю где-то в коде, даже если поле фактически не назначено в статическомконструктор.Таким образом, кажется, что вызов метода в интерфейсе не заставляет работать статический конструктор, а делает доступ к полю.Почему это так?И где это упоминается в спецификации?

1 Ответ

10 голосов
/ 14 марта 2011

Мне кажется , что, хотя вы можете определить .cctor на интерфейсе в CLI, это бесполезно.Раздел I, § 8.9.5, гласит:

Если помечен BeforeFieldInit, то метод инициализатора типа выполняется во время или за некоторое время до первого доступа к любому статическому полю, определенному для этого типа.Если не помечен BeforeFieldInit, то метод инициализатора этого типа выполняется в (т. Е. Инициируется): первый доступ к любому статическому полю этого типа, или первый вызов любого статического метода этого типа, или первый вызов любого экземпляра или виртуального методаэтого типа, если это тип значения или первый вызов любого конструктора для этого типа. Выполнение любого метода инициализатора любого типа не приведет к автоматическому выполнению каких-либо методов инициализатора, определенных его базовым типом, или любых интерфейсов, которые реализует тип.

(выделено мной) Что означаетинициализатор типа в интерфейсе вообще не вызывается автоматически.Если вы хотите, чтобы он вызывался, вам (IMHO) нужно явно вызывать его во всех реализующих классах, например:

.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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...