c# - 显式标记派生类为基类的实现接口(interface)

标签 c# inheritance interface

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 of C. The implementation of a particular interface member I.M, where I is the interface in which the member M is declared, is determined by examining each class or struct S, starting with C and repeating for each successive base class of C, until a match is located:

  • If S contains a declaration of an explicit interface member implementation that matches I and M, then this member is the implementation of I.M.
  • Otherwise, if S contains a declaration of a non-static public member that matches M, then this member is the implementation of I.M. If more than one member matches, it is unspecified which member is the implementation of I.M. This situation can only occur if S 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 in TextBox hides the Paint method in Control, but it does not alter the mapping of Control.Paint onto IControl.Paint, and calls to Paint through class instances and interface instances will have the following effects

Control 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 maps IControl.Paint onto Control.IControl.Paint doesn’t affect the re-implementation in MyControl, which maps IControl.Paint onto MyControl.Paint.

关于c# - 显式标记派生类为基类的实现接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46541462/

相关文章:

c# - 识别相同 OleDbException 类型的异常

c# - 删除具有已知开始和结束字符串的字符串 c#

java - Hibernate 继承建模

c++ - 关于标准中虚函数描述的一个问题

go - 将事物的 channel 作为 Go 中的接口(interface) channel 传递

java - 我可以使用 HashMap 在 Spring Boot 中选择要 Autowiring 的接口(interface) (DAO) 吗?

c# - 在 C# 中对小代码示例进行基准测试,可以改进此实现吗?

c# - 打印 <div> 标签内的图表

c++ - 从基指针列表循环 (OOD) 调用派生类方法

C#:接口(interface)继承getters/setters