[英]Why does the C# compiler insert an explicit interface implementation?
I ran into a strange C# edge case and am looking for a good work-around. 我遇到了一个奇怪的C#边缘案例,我正在寻找一个好的解决方案。
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. 但是,如果我将“ClassIDoNotControl”移动到另一个程序集中,我就达不到我的预期。 Instead, I see "MyCompany.IInterfaceIDoControl.SomeMethod" for the output implying an extra stack frame.
相反,我看到输出暗示额外堆栈帧的“MyCompany.IInterfaceIDoControl.SomeMethod”。
The reason is that under the covers, the C# compiler is changing "ClassIDoControl" to look like this: 原因是在C#编译器下,将“ClassIDoControl”更改为如下所示:
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). 简短回答: CLR要求实现接口方法的所有方法都必须是虚拟的( 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.
Reflector证实了这一点。 (“final” is the CLR terminology for “sealed” in C#.)
(“final”是C#中“密封”的CLR术语。)
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. 所以你最后一个问题的答案是“有没有办法避免这种情况?”,遗憾的是没有。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.