C#中派生类无需virtual/abstract重写基类接口方法的原理
关于C#显式接口实现与子类方法的疑问
先看这段基于.NET 5和C# 9.0的代码:
interface IPayable { public int Pay(); } class Human : IPayable { int IPayable.Pay() { return 1; } } class Debtor : Human { int Pay() { return 0; } }
问题
为什么Debtor.Pay()方法不需要基类方法标记virtual或abstract,也没有隐藏基类功能的警告,就能“重写”基类的接口实现?
解答
你这里的核心误解是:Debtor的Pay方法根本不是在重写或隐藏基类的接口实现,两者是完全独立的两个方法,原因如下:
- 基类
Human中的IPayable.Pay()是显式接口实现,这种方法默认是private访问级别(无需显式声明),且不属于Human类的公共/受保护成员,在子类Debtor中完全不可见。 Debtor里定义的Pay()是一个全新的私有实例方法,它和基类的显式接口实现不存在命名冲突——基类的那个方法只有在把Human实例转换为IPayable接口时才能被调用,而子类自己的Pay()仅能在Debtor内部访问。- 编译器不会给出隐藏警告,是因为基类中没有可供隐藏的、对子类可见的同名方法。如果基类的Pay是公开的非显式实现(比如
public int Pay()),子类再定义同名私有方法时才会触发隐藏警告。
举个验证例子:
Human human = new Debtor(); // 编译报错:Human类本身无Pay方法,必须转成IPayable才能调用 // human.Pay(); IPayable payable = new Debtor(); // 调用的是Human的显式接口实现,返回1,而非Debtor的Pay方法 Console.WriteLine(payable.Pay()); // 输出1 Debtor debtor = new Debtor(); // 仅Debtor内部能调用自身的Pay方法,外部无法访问
内容的提问来源于stack exchange,提问作者Oleksa Krav
相关产品推荐
相关产品推荐

