簡體   English   中英

在C#中使用靜態方法實現接口

[英]Implementing Interface with static methods in C#

假設我有以下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) { }
    }

是否可以在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
        }
    }

並成功使用C#代碼中實現的類:

        var testImpl = new TestImpl();
        testImpl.InstMethod("I'm static!"); 

但是在C#中實現這個接口呢?

令人驚訝的是(至少對我來說),你的IL代碼編譯和驗證(使用PEVerify)很好(假設你添加了一些.assembly指令)。

這得到了CLI規范的支持(§I.8.9.4接口類型定義):

[...]接口類型定義不應提供接口類型值(即實例字段)的字段定義,盡管它可以聲明靜態字段。

[...]接口類型定義可以定義和實現靜態方法,因為靜態方法與接口類型本身相關聯,而不是與類型的任何值相關聯。

但這樣做不符合CLS:

CLS規則19:符合CLS的接口不應定義靜態方法,也不應定義字段。

您可以在C#中實現該接口。 以下代碼編譯並正常工作:

class Test : ITest
{
    public void InstMethod(string s)
    { }
}

但看起來你無法從C#訪問靜態字段或靜態方法。

這是對您的評論的回復:

我認為即使通過反射也無法獲得實現的靜態:var m = new Test()。GetType()。GetMethods(BindingFlags.Static | BindingFlags.Public); - user2341923

請記住,方法的聲明類型是接口,因此必須從接口類型中提取方法定義。 粗略地說,我認為這應該工作(使用一些linq擴展添加)

var m = new Test().GetType().GetInterfaces().Where(
        i => i.IsAssignableFrom(
        typeof ITest)).First().GetMethods(
        BindingFlags.Static | BindingFlags.Public);

對於任何已實現的接口成員都是如此。 實例或其他。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM