10

考虑以下代码示例:

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)); // Output 55, --> im not sure from this output. I can compile the code but not execute it!

IPowerPlayer powerPlayer = new Player();
Console.WriteLine(powerPlayer.Attack(5)); // Output 55

ILimitedPlayer limitedPlayer = new Player();
Console.WriteLine(limitedPlayer.Attack(5)); // Output 15

我的问题出在代码上:

Console.WriteLine(player.Attack(5)); // Output 55

问题是:输出应该是15还是55?!

根据 .NET 团队的说法:

决定:于 2017 年 4 月 11 日做出:运行 I2.M,这是运行时最明确的最具体的覆盖。

我不确定这里是因为重写界面上的关键字“new”吗?正确的行为应该是什么?

如果您需要从源代码编译它,您可以从以下网址下载源代码: https ://github.com/alugili/Default-Interface-Methods-CSharp-8

4

2 回答 2

7

是的,这是因为new实际上隐藏了父类型的派生类型实现的关键字,因为它与之前的类的行为完全相同,我们称之为Shadowing 概念

因此输出将是55,因为您有object类型IPlayer的引用,并且' 的方法由于其签名中的关键字而被隐藏PlayerILimitedPlayerAttackIPlayernew

于 2018-04-16T15:16:46.367 回答
3

我想说,如果没有 C#8 编译器,你可以对它应该如何工作有一个“很好的猜测”。我们在这里拥有的基本上是:

public interface IPlayer {
    // method 1
    int Attack(int amount);
}

public interface IPowerPlayer : IPlayer {
    // no methods, only provides implementation
}

public interface ILimitedPlayer : IPlayer {
    // method 2, in question also provides implementation
    new int Attack(int amount);
}

所以我们有 2 个接口方法(具有相同的签名),并且一些接口(IPowerPlayerILimitedPlayer)提供这些方法的实现。我们可以在Player类本身中提供实现来实现类似的功能:

public class Player : IPowerPlayer, ILimitedPlayer {
    int IPlayer.Attack(int amount) {
        return amount + 50;
    }

    int ILimitedPlayer.Attack(int amount) {
        return amount + 10;
    }
}

然后从问题输出运行代码:

55

55

15

我认为原因比较清楚。

于 2018-04-16T16:07:42.033 回答