在C#中使用静态方法实现接口

use*_*923 7 .net c# clr il

假设我有以下ILAsm代码:

    .class public interface abstract ITest
    {
        .field public static int32 counter

        .method public static void StaticMethod(string str)
        {
            ldarg.0
            call void [mscorlib]System.Console::WriteLine(string)
            ret
        }

        .method public virtual abstract void InstMethod(string) { }
    }
Run Code Online (Sandbox Code Playgroud)

是否可以在C#中定义实现此ITest接口的类?

我可以在ILAsm中实现这个接口:

    .class public TestImpl extends [mscorlib]System.Object implements ITest
    {
        .method public virtual void InstMethod(string str)
        {
            ldarg.1
            call void ITest::StaticMethod(string)
            ret
        }

        .method public specialname rtspecialname instance void .ctor()
        {
            ldarg.0
            call instance void .base::.ctor()
            ret
        }
    }
Run Code Online (Sandbox Code Playgroud)

并成功使用C#代码中实现的类:

        var testImpl = new TestImpl();
        testImpl.InstMethod("I'm static!"); 
Run Code Online (Sandbox Code Playgroud)

但是如何在C#中实现这个接口呢?

svi*_*ick 6

令人惊讶的是(至少对我来说),你的IL代码编译和验证(使用PEVerify)很好(假设你添加了一些.assembly指令).

这得到了CLI规范的支持(§I.8.9.4接口类型定义):

[...]接口类型定义不应提供接口类型值(即实例字段)的字段定义,尽管它可以声明静态字段.

[...]接口类型定义可以定义和实现静态方法,因为静态方法与接口类型本身相关联,而不是与类型的任何值相关联.

但这样做不符合CLS:

CLS规则19:符合CLS的接口不应定义静态方法,也不应定义字段.

您可以在C#中实现该接口.以下代码编译并正常工作:

class Test : ITest
{
    public void InstMethod(string s)
    { }
}
Run Code Online (Sandbox Code Playgroud)

但看起来你无法从C#访问静态字段或静态方法.