C# 8 默认接口方法:多接口实现调用结果存疑
这问题我刚看到的时候也琢磨了下,其实核心是C#里显式接口实现和接口方法隐藏的规则在起作用,我给你一步步拆解:
首先先把你的代码贴出来方便对照:
public interface IPlayer { int Attack(int amount); } public interface IPowerPlayer: IPlayer { int IPlayer.Attack(int amount) { return amount + 50; } } public interface ILimitedPlayer: IPlayer { new int Attack(int amount) { return amount + 10; } } public class Player : IPowerPlayer, ILimitedPlayer { }
执行代码:
IPlayer player = new Player(); Console.WriteLine(player.Attack(5)); // 输出55
关键知识点1:显式接口实现的特殊性
IPowerPlayer里的int IPlayer.Attack(int amount)是显式接口实现——这种写法的意思是:我实现的是IPlayer接口的Attack方法,而且这个方法只能通过IPlayer类型的引用才能调用,不属于IPowerPlayer自己的方法(哪怕IPowerPlayer继承自IPlayer)。
关键知识点2:new关键字是“隐藏”而非“重写”
ILimitedPlayer里的new int Attack(int amount)用了new关键字,它的作用是隐藏继承自IPlayer的Attack方法,而不是重写。也就是说,这个Attack是ILimitedPlayer自己独有的方法,和IPlayer的Attack是两个完全不同的方法——只有当你用ILimitedPlayer类型的引用调用时,才会触发这个方法。
为什么输出55?
当你把Player实例赋值给IPlayer类型的变量时,C#会去寻找这个类中直接实现IPlayer.Attack的方法。而你的代码里,只有IPowerPlayer用显式实现的方式完成了IPlayer.Attack的实现,ILimitedPlayer的Attack是自己的方法,和IPlayer的Attack没关系。
所以调用player.Attack(5)时,实际执行的是IPowerPlayer里显式实现的IPlayer.Attack,也就是5 + 50 = 55。
额外验证:换个类型调用试试
如果我们换不同的接口类型调用,结果就不一样了:
// 用ILimitedPlayer类型调用,会触发它自己的Attack方法 ILimitedPlayer limited = new Player(); Console.WriteLine(limited.Attack(5)); // 输出15 // 用IPowerPlayer类型调用,因为它继承IPlayer,实际还是调用显式实现的IPlayer.Attack IPowerPlayer power = new Player(); Console.WriteLine(power.Attack(5)); // 输出55
这样是不是就清晰多啦?
内容的提问来源于stack exchange,提问作者Bassam Alugili

