为什么这个 C# 代码返回它的作用 [英] Why does this C# code return what it does

查看:34
本文介绍了为什么这个 C# 代码返回它的作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人可以帮我理解为什么这个代码片段返回Bar-Bar-Quux"?即使在阅读了界面之后,我也很难理解这一点.

Can someone please help me understand why this code snippet returns "Bar-Bar-Quux"? I'm having a hard time understanding this even after reading up on interfaces.

interface IFoo
{ 
    string GetName();
}

class Bar : IFoo
{
    public string GetName() { return "Bar"; }
}

class Baz : Bar
{
    public new string GetName() { return "Baz"; }
}

class Quux : Bar, IFoo
{
    public new string GetName() { return "Quux"; }
}

class Program
{
    static void Main()
    {
        Bar f1 = new Baz();
        IFoo f2 = new Baz();
        IFoo f3 = new Quux();
        Console.WriteLine(f1.GetName() + "-" + f2.GetName() + "-" + f3.GetName());
    }
}

推荐答案

这里发生了两件事.一是会员隐藏.这是相当有名的,并且在其他地方都有介绍.另一个鲜为人知的功能是 C# 5 规范第 13.4.6 节中介绍的接口重新实现.引用:

There are two things happening here. One is member hiding. This is fairly well-known and covered elsewhere. The other, less-known feature is interface re-implementation covered in section 13.4.6 of the C# 5 specification. To quote:

允许继承接口实现的类通过将其包含在基类列表中来重新实现接口.接口的重新实现遵循与接口的初始实现完全相同的接口映射规则.因此,继承的接口映射对为重新实现接口而建立的接口映射没有任何影响.

A class that inherits an interface implementation is permitted to re-implement the interface by including it in the base class list. A re-implementation of an interface follows exactly the same interface mapping rules as an initial implementation of an interface. Thus, the inherited interface mapping has no effect whatsoever on the interface mapping established for the re-implementation of the interface.

继承的公共成员声明和继承的显式接口成员声明参与重新实现的接口的接口映射过程.

Inherited public member declarations and inherited explicit interface member declarations participate in the interface mapping process for re-implemented interfaces.

f1.GetName() 的结果是Bar",因为方法 Baz.GetName 隐藏了 Bar.GetName>f1 被声明为 Bar 类型.除非明确声明为虚拟和重写,否则不会分派到运行时类型的实现.

The result for f1.GetName() is "Bar" because the method Baz.GetName is hiding Bar.GetName and f1 is declared as type Bar. There is no dispatch to the run-time type's implementation unless it is explicitly declared as virtual and overridden.

同理,对于f2.GetName()来说,Baz.GetNameBar中隐藏了实现,所以在使用时不会被调用通过对接口的引用进行调度.接口映射"到 Bar 中声明的方法,因为这是声明接口的类型.Baz 是否具有同名的兼容方法并不重要.接口映射规则在规范的 13.4.4 节中定义.如果 GetNameBar 中被声明为 virtual,它可以被覆盖,然后通过接口调用.因此,结果也是Bar".

Similarly, for f2.GetName(), Baz.GetName is hiding the implementation in Bar, so it is not called when using dispatch through a reference to the interface. The interface is "mapped" to the method declared in Bar because that is the type on which the interface was declared. It does not matter that Baz has a compatible method with the same name. The rules for interface mapping are defined in section 13.4.4 of the spec. If GetName had been declared virtual in Bar, it could be overridden, which then would be called through the interface. The result is therefore also "Bar".

对于 f3.GetName()Quux 重新实现了 IFoo,因此它可以定义自己到 GetName<的映射/代码>.请注意,它还隐藏了从 Bar 继承的实现.没有必要使用 new 来重新实现,它只是抑制了关于隐藏的警告.因此结果是Quux".

For f3.GetName(), Quux re-implements IFoo so it gets to define its own mapping to GetName. Note that it also hides the implementation inherited from Bar. It is not necessary to use new to do the re-implementation, it simply suppresses the warning about hiding. Therefore the result is "Quux".

这就解释了您看到的输出:Bar-Bar-Quux"

So that explains the output that you see: "Bar-Bar-Quux"

这个埃里克·利珀特 (Eric Lippert) 的帖子 讨论了这个棘手功能的更多细微差别.

This post by Eric Lippert discuss some more nuances in this tricky feature.

这篇关于为什么这个 C# 代码返回它的作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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