为什么这个C#code返回它做什么 [英] Why does this C# code return what it does

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

问题描述

有人可以帮我明白为什么code片断返回酒吧酒吧-QUUX?我有即使在接口读取后很难理解这一点。

 接口IFoo的
{
    字符串的GetName();
}Bar类:IFoo的
{
    公共字符串的GetName(){返回BAR; }
}巴兹类:酒吧
{
    大众新的字符串的GetName(){返回巴兹 }
}类QUUX:酒吧,IFoo的
{
    大众新的字符串的GetName(){返回QUUX }
}类节目
{
    静态无效的主要()
    {
        酒吧F1 =新巴兹();
        IFoo的F2 =新巴兹();
        IFoo的F3 =新QUUX();
        Console.WriteLine(f1.GetName()+ - + f2.GetName()+ - + f3.GetName());
    }
}


解决方案

有两件事情发生在这里。一个是成员躲藏。这是相当知名的,覆盖别处。其他的,鲜为人知的特点是界面重新实施覆盖在C#5规范的13.4.6节。引用:


  

这是继承了一个接口实现类允许的再落实,包括它的基类列表的接口。重新实现一个接口都遵循完全相同的接口映射规则为初步实施的接口。因此,继承的接口映射有任何关于重新实现的接口建立的接口映射没有影响。



  

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


f1.GetName结果()是酒吧,因为该方法 Baz.GetName 是隐藏 Bar.GetName F1 被声明为类型酒吧。没有调度的运行时类型的实现,除非它被明确宣布为虚拟和覆盖。

同样,对于 f2.GetName() Baz.GetName 是躲在实施酒吧,所以通过对接口的引用使用调度时,它不叫。该接口被映射到声明的方法吧,因为这是要在其声明的接口类型。这不要紧,巴兹具有相同名称的兼容方法。接口映射的规则在规范第13.4.4规定。如果的GetName 已宣布在酒吧虚拟的,它可以被覆盖,然后将通过接口来调用。因此,结果也是栏。

有关 f3.GetName() QUUX 重机具的IFoo 因此它的定义自己的映射的GetName 。请注意,它也隐藏从酒吧继承的实现。它是没有必要使用新做重新实现,它简单地SUP presses的警告有关隐藏。因此结果是QUUX

这样解释,你看到的输出:酒吧酒吧-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());
    }
}

解决方案

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.

and

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

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.

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".

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".

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

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

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

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