interface IBase
{
string Name { get; }
}
class Base : IBase
{
public Base() => this.Name = "Base";
public string Name { get; }
}
class Derived : Base//, IBase
{
public Derived() => this.Name = "Derived";
public new string Name { get; }
}
class Program
{
static void Main(string[] args)
{
IBase o = new Derived();
Console.WriteLine(o.Name);
}
}
在这种情况下,输出将为“Base”。
如果我明确声明 Derived 实现了 IBase(实际上它已经由基类 Base 实现并且这样的注释似乎没有用)输出将是“Derived”
class Derived : Base, IBase
{
public Derived() => this.Name = "Derived";
public new string Name { get; }
}
这种行为的原因是什么?
VS 15.3.5,C# 7
最佳答案
它在 C# 5 规范的第 13.4.4 到 13.4.6 节中有解释。下面引用了相关部分,但基本上,如果您显式声明一个类实现了一个接口(interface),则会再次触发接口(interface)映射,因此编译器将那个类作为用于计算每个类的实现的类接口(interface)成员映射到。
13.4.4 Interface mapping
A class or struct must provide implementations of all members of the interfaces that are listed in the base class list of the class or struct. The process of locating implementations of interface members in an implementing class or struct is known as interface mapping.
Interface mapping for a class or struct
C
locates an implementation for each member of each interface specified in the base class list ofC
. The implementation of a particular interface memberI.M
, whereI
is the interface in which the memberM
is declared, is determined by examining each class or structS
, starting withC
and repeating for each successive base class ofC
, until a match is located:
- If
S
contains a declaration of an explicit interface member implementation that matchesI
andM
, then this member is the implementation ofI.M
.- Otherwise, if
S
contains a declaration of a non-static public member that matches M, then this member is the implementation ofI.M
. If more than one member matches, it is unspecified which member is the implementation ofI.M
. This situation can only occur ifS
is a constructed type where the two members as declared in the generic type have different signatures, but the type arguments make their signatures identical....
13.4.5 Interface implementation inheritance
A class inherits all interface implementations provided by its base classes. Without explicitly re-implementing an interface, a derived class cannot in any way alter the interface mappings it inherits from its base classes. For example, in the declarations
interface IControl { void Paint(); } class Control: IControl { public void Paint() {...} } class TextBox: Control { new public void Paint() {...} }
the
Paint
method inTextBox
hides thePaint
method inControl
, but it does not alter the mapping ofControl.Paint
ontoIControl.Paint
, and calls toPaint
through class instances and interface instances will have the following effectsControl c = new Control(); TextBox t = new TextBox(); IControl ic = c; IControl it = t; c.Paint(); // invokes Control.Paint(); t.Paint(); // invokes TextBox.Paint(); ic.Paint(); // invokes Control.Paint(); it.Paint(); // invokes Control.Paint();
...
13.4.6 Interface reimplementation
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. For example, in the declarations
interface IControl { void Paint(); } class Control: IControl { void IControl.Paint() {...} } class MyControl: Control, IControl { public void Paint() {} }
the fact that
Control
mapsIControl.Paint
ontoControl.IControl.Paint
doesn’t affect the re-implementation inMyControl
, which mapsIControl.Paint
ontoMyControl.Paint
.
关于c# - 显式标记派生类为基类的实现接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46541462/