【问题标题】:Default Interface Methods in C# 8C# 8 中的默认接口方法
【发布时间】:2018-04-16 15:12:39
【问题描述】:

考虑以下代码示例:

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 团队的说法:

Decision: Made 2017-04-11: Runs I2.M, which is the unambiguously most specific override at runtime.

由于被覆盖的界面上的关键字“new”,我在这里不确定?正确的行为应该是什么?

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

【问题讨论】:

  • "我可以编译代码但不能执行它!"为什么你不能执行它? IMO,输出将是 55
  • 我认为这与IPowerPlayer Attack 方法显式实现IPlayer 方法,而ILimitedPlayer Attack 方法隐式实现它有关。或者可能是因为它使用 new 关键字遮蔽了它。这可能是两者的结合。
  • @BassamAlugili 这搞砸了。我不觉得它应该编译允许你有两个方法,相同的名称,不同的功能,在每个接口上。
  • @CamiloTerevinto 执行不起作用我已经构建了分支并启动了该功能。一切工作正常,编译,智能等,除了执行时出现错误 --> 接口中不允许使用方法
  • 也许您应该等待 C#8 编译器?

标签: c# c#-8.0 default-interface-member


【解决方案1】:

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

所以输出将是 55,因为您有 Player 对象的 IPlayer 类型的引用,而 ILimitedPlayerAttack 方法对 IPlayer 隐藏,因为 @ 987654329@ 签名中的关键字

【讨论】:

  • @CamiloTerevinto 对此感到抱歉,进一步澄清
  • 我不完全确定这是正确的答案。阅读 OP 的评论:“除了执行时出现错误--> 接口中不允许使用方法”
  • @CamiloTerevinto C# 过去不支持任何可见性属性,如接口中的公共私有,所以我对 C# 8 还不太熟悉,但如果上面的代码编译 OP,那么看起来现在我们可以定义跨度>
  • @MichaelPuckettII 你真的不明白我的评论。我熟悉正在做的事情,并且 OP 发布了运行时异常,而不是我
  • 令我惊讶的是,我们正在讨论一个尚未决定的功能(回购仍然调用 newopen issue),我什至不确定这一点代码编译。
【解决方案2】:

我想说,如果没有 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 个接口方法(具有相同的签名),并且一些接口(@98​​7654322@ 和ILimitedPlayer)提供了这些方法的实现。我们可以在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

而且我认为原因比较清楚。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-28
    • 1970-01-01
    • 2020-04-11
    • 2015-07-31
    • 2014-06-06
    • 1970-01-01
    • 2019-01-28
    相关资源
    最近更新 更多