gpt4 book ai didi

c# - 为什么 C# 编译器会插入显式接口(interface)实现?

转载 作者:IT王子 更新时间:2023-10-29 04:09:34 32 4
gpt4 key购买 nike

我遇到了一个奇怪的 C# 边缘案例,正在寻找一个好的解决方法。

有一个我无法控制的类,如下所示:

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

我想在我 控制的类中继承此类。另外,我想在上面指定一个接口(interface):

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);
}
}

有没有办法通过显式实现的接口(interface)来避免编译器生成的额外间接层?

最佳答案

简短回答:CLR 要求所有实现接口(interface)方法的方法都必须是虚拟的(Ecma 335 Partition II 第 12.1 节)。

长答案:

  • 如果基类中的方法已经是虚方法,则不需要额外的东西:接口(interface)方法可以绑定(bind)到它。

  • 如果基类中的方法不是虚拟的,但在同一个程序集中,偷偷摸摸的编译器实际上使它成为虚拟的和最终的。 Reflector 证实了这一点。 (“final”是 C# 中“密封”的 CLR 术语。)

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

很遗憾,您最后一个问题“有没有办法避免这种情况?”的答案是否定的。

关于c# - 为什么 C# 编译器会插入显式接口(interface)实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3668322/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com