为什么C#编译器插入一个显式接口实现?

我遇到了一个奇怪的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要求实现接口方法的所有方法都必须是virtual(Ecma 335 Partition II Section 12.1)。

长答案:

>如果基类中的方法已经是虚拟的,则不需要额外的:接口方法可以绑定到它。
>如果基类中的方法不是虚拟的,但是在同一程序集中,那么sneaky编译器实际上使它成为virtual和final。反射器证实了这一点。 (“final”是C#中“sealed”的CLR术语)。
>如果基类中的方法不是虚拟的并且在另一个程序集中,那么显然编译器不能这样做,因为它不能修改已经编译的程序集。因此,这里唯一的选择是插入一个实现接口方法的重定向方法。像实现接口方法的所有方法一样,它也被标记为virtual和final。

所以,你最后一个问题的答案,“有办法避免这个吗?”,不幸的是没有。

http://stackoverflow.com/questions/3668322/why-does-the-c-sharp-compiler-insert-an-explicit-interface-implementation

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:为什么C#编译器插入一个显式接口实现?