为什么C#编译器插入一个显式接口实现? [英] Why does the C# compiler insert an explicit interface implementation?

查看:129
本文介绍了为什么C#编译器插入一个显式接口实现?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个奇怪的C#边缘情况,并寻找一个好的工作。



有一个类,我不控制,看起来像这样:

  namespace其他公司
{
public class ClassIDoNotControl
{
public void SomeMethod (字符串参数)
{
Console.WriteLine((New StackFrame(1).GetMethod()。Name));
}
}
}

我想继承从这个类中我的 控制。此外,我想在其上指定一个接口:

  interface IInterfaceIDoControl 
{
void SomeMethod (string argument);
}

class ClassIDoControl:OtherCompany.ClassIDoNotControl,IInterfaceIDoControl
{
}

如果所有这些文件在同一个程序集中,一切都很棒:

 命名空间MyCompany 
{
class Program
{
static void Main(string [] args)
{
IInterfaceIDoControl i = new ClassIDoControl
i.SomeMethod(Hello World!); // PrintsMain
}
}
}

但是,如果我将ClassIDoNotControl移动到另一个程序集,我没有得到我的预期。相反,我看到MyCompany.IInterfaceIDoControl.SomeMethod的输出意味着一个额外的堆栈框架。



原因是在覆盖下,C#编译器正在改变ClassIDoControl 看起来像这样:

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

有没有办法避免这个编译器生成的额外具有明确实现的接口的间接层?

解决方案

实现一个接口方法必须是virtual( Ecma 335 Partition II Section 12.1)。



长回答: b


  • 如果基类中的方法已经是virtual,那么不需要额外的东西:接口方法可以绑定到它。

    li>
  • 如果基类中的方法是不是 virtual,但是在同一个程序集中,实际编译器实际上使它成为virtual和final 。反射器证实了这一点。 (final是C#中sealed的CLR术语。)


  • 方法在基类中不是虚拟的,在另一个程序集中,那么显然编译器不能这样做,因为它不能修改已经编译的程序集。因此,这里唯一的选择是插入一个实现接口方法的重定向方法。像实现接口方法的所有方法一样,它也被标记为 virtual和final




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


I ran into a strange C# edge case and am looking for a good work-around.

There is a class that I do not control that looks like this:

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

I'd like to inherit from this class in a class I do control. Additionally, I'd like to specify an interface on it:

interface IInterfaceIDoControl
{
    void SomeMethod(string argument);
}

class ClassIDoControl : OtherCompany.ClassIDoNotControl, IInterfaceIDoControl
{
}

If all of these files are in the same assembly, everything works great:

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

But, if I move "ClassIDoNotControl" into another assembly, I don't get what I expected. Instead, I see "MyCompany.IInterfaceIDoControl.SomeMethod" for the output implying an extra stack frame.

The reason is that under the covers, the C# compiler is changing "ClassIDoControl" to look like this:

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

Is there a way to avoid this compiler-generated extra layer of indirection with explicitly implemented interfaces?

解决方案

Short answer: The CLR requires that all methods that implement an interface method must be virtual (Ecma 335 Partition II Section 12.1).

Long answer:

  • If the method in the base class is already virtual, then nothing extra is needed: the interface method can be bound to it.

  • If the method in the base class is not virtual, but in the same assembly, the sneaky compiler actually makes it virtual and final. Reflector confirms this. ("final" is the CLR terminology for "sealed" in C#.)

  • If the method in the base class is not virtual and in another assembly, then obviously the compiler can’t do this because it can’t modify the already-compiled assembly. Therefore, the only option here is to insert a redirect method that implements the interface method. Like all methods that implement an interface method, it too is marked virtual and final.

So the answer to your last question, "Is there a way to avoid this?", is unfortunately no.

这篇关于为什么C#编译器插入一个显式接口实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆