为什么这个C#code返回它做什么 [英] Why does this C# code return what it does
问题描述
有人可以帮我明白为什么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 methodBaz.GetName
is hidingBar.GetName
andf1
is declared as typeBar
. 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 inBar
, so it is not called when using dispatch through a reference to the interface. The interface is "mapped" to the method declared inBar
because that is the type on which the interface was declared. It does not matter thatBaz
has a compatible method with the same name. The rules for interface mapping are defined in section 13.4.4 of the spec. IfGetName
had been declared virtual inBar
, it could be overridden, which then would be called through the interface. The result is therefore also "Bar".For
f3.GetName()
,Quux
re-implementsIFoo
so it gets to define its own mapping toGetName
. Note that it also hides the implementation inherited fromBar
. 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屋!