簡體   English   中英

為什么C#編譯器插入顯式接口實現?

[英]Why does the C# compiler insert an explicit interface implementation?

我遇到了一個奇怪的C#邊緣案例,我正在尋找一個好的解決方案。

有一個我無法控制的類看起來像這樣:

namespace OtherCompany
{
    public class ClassIDoNotControl
    {
        public void SomeMethod(string argument)
        {
            Console.WriteLine((new StackFrame(1).GetMethod().Name));
        }
    }
}

我想從這個類中的一類我控制繼承。 另外,我想在其上指定一個接口:

interface IInterfaceIDoControl
{
    void SomeMethod(string argument);
}

class ClassIDoControl : OtherCompany.ClassIDoNotControl, IInterfaceIDoControl
{
}

如果所有這些文件都在同一個程序集中,那么一切都很好:

namespace MyCompany
{
    class Program
    {
        static void Main(string[] args)
        {
            IInterfaceIDoControl i = new ClassIDoControl();
            i.SomeMethod("Hello World!"); // Prints "Main"
        }
    }
 }

但是,如果我將“ClassIDoNotControl”移動到另一個程序集中,我就達不到我的預期。 相反,我看到輸出暗示額外堆棧幀的“MyCompany.IInterfaceIDoControl.SomeMethod”。

原因是在C#編譯器下,將“ClassIDoControl”更改為如下所示:

class ClassIDoControl : OtherCompany.ClassIDoNotControl, IInterfaceIDoControl
{
    void IInterfaceIDoControl.SomeMethod(string argument)
    {
        base.SomeMethod(argument);
    }
}

有沒有辦法避免這個編譯器生成的額外的間接層與明確實現的接口?

簡短回答: CLR要求實現接口方法的所有方法都必須是虛擬的( Ecma 335 Partition II Section 12.1)。

答案很長:

  • 如果基類中的方法已經是虛擬的,則不需要額外的任何內容:接口方法可以綁定到它。

  • 如果基類中的方法不是虛擬的,而是在同一個程序集中,那么偷偷摸摸的編譯器實際上使它成為虛擬和最終的 Reflector證實了這一點。 (“final”是C#中“密封”的CLR術語。)

  • 如果基類中的方法不是虛擬的並且在另一個程序集中,那么顯然編譯器不能這樣做,因為它無法修改已經編譯的程序集。 因此,此處唯一的選擇是插入實現接口方法的重定向方法。 與實現接口方法的所有方法一樣,它也標記為虛擬和最終

所以你最后一個問題的答案是“有沒有辦法避免這種情況?”,遺憾的是沒有。

暫無
暫無

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

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