【问题标题】:Why can't an interface implementation return a more specific type?为什么接口实现不能返回更具体的类型?
【发布时间】:2012-05-29 09:44:40
【问题描述】:

如果一个接口指定了一个属性或方法来返回另一个接口,为什么不允许第一个接口的实现将返回类型“更改”为更具体的类型?

我们举个例子来说明:

interface IFoo
{
    IBar GetBar();
}
interface IBar
{ }

class Foo : IFoo
{
    // This is illegal, we are not implementing IFoo properly
    public Bar GetBar()
    {
        return new Bar();
    }
}

class Bar : IBar
{ }

我知道如何让它发挥作用,这不是我关心的。

我可以:

  • GetFoo()的返回类型更改为IBar,或者
  • 显式实现接口,只需从IFoo.GetBar() 方法调用GetBar

我真正要问的是不只是允许上面的代码编译的原因。是否存在上述不履行IFoo指定的合同的情况。

【问题讨论】:

  • 还有第三种方式,比上面两种方式稍微方便一些。您可以使用抽象类来实现接口。然后,在你的“具体”类中继承抽象类而不是接口。然后在您的“具体”类中,您可以使用“new”关键字隐藏基本方法。它对我来说工作得很好。
  • 我觉得 BrainSlugs83 的评论在这里是一个答案,因为它提供了一个不错的解决方法。

标签: c# interface language-design overloading


【解决方案1】:

通常情况下,我会说这是一个平衡好处与支持此类功能所增加的复杂性的案例。 (所有功能都需要努力设计、记录、实现、测试,然后开发人员也需要接受有关它们的教育。)请注意,如果您想支持返回实现接口的值类型,可能会有一些显着的复杂性,例如(因为这会以不同的表示形式结束,而不仅仅是参考)。

在这种情况下,我不相信 CLR 甚至支持这样的功能,这使得 C# 很难干净地做到这一点。

我同意这将是一个有用的功能,但我怀疑它没有被认为足够有用,不足以保证所需的额外工作。

【讨论】:

  • 乔恩我有问题吗? 1分钟怎么写这么多?
  • +1 因为“...增加了...的复杂性”这一点,但我不确定它是否有用。毕竟接口是一个契约,如果你需要一个类似的方法,你可以显式地实现接口方法并添加另一个具有 required 返回类型的方法,所以......那是为了什么?
  • @Adriano:你可以,是的。但是你必须这样做很烦人,并且显式接口实现有其自身的缺点和复杂性。我尽可能避免显式接口实现,如果支持协变返回类型,那将是另一个我可以避免的地方:)
  • @NikhilAgrawal:并不是真的全部在一分钟内写完。我确实编辑并添加了更多信息......
  • @Adriano:考虑一个派生自另一个使用显式接口实现的具体类。如果您想覆盖该接口实现,但仍使用原始实现,则会遇到问题 - 您不能调用 base.Foo(),但转换为接口最终会递归回您的实现。它也不能很好地与dynamic 配合使用。
【解决方案2】:

您要询问的功能称为“返回类型协方差”。正如on Wikipedia 所指出的,Java 和 C++ 都有它,这也许让 C# 没有它令人惊讶。

Eric Lippert 在 cmets 中确认此答案未实施此功能,因为它被认为不值得实施。 (此答案的先前修订版将这一决定的责任分配给了 Eric 个人;他说这是不正确的,如果有人对此负责,那就是 Anders Hejlsberg。)

无论如何,现在有各种建议将其添加到语言中(请参阅https://github.com/dotnet/roslyn/issues/357https://github.com/dotnet/csharplang/blob/master/proposals/covariant-returns.mdhttps://github.com/kingces95/coreclr/issues/2),因此它可能会在未来几年内实施。根据这些讨论,听起来并没有什么深刻的理由说明 C# 中不应存在该功能原则上 - 相反,到目前为止,它从未被认为值得任何人努力实现。

【讨论】:

  • 该功能是在我加入 C# 设计团队前几年添加到 Java 中的,所以当时没有考虑我的意见。当我在 C# 设计团队时,据我回忆,设计团队从未考虑过这个问题。因此,更准确地说,Anders 认为这不值得付出努力。我不认为这是一个坏特性,如果 C# 有它,我会使用它。我同意还有很多我会优先考虑的功能。
【解决方案3】:

它没有实现,因为他们认为该功能不能证明付出的努力是合理的。但也有好消息。

此功能已在 post by Mads Torgersen in March 2020 中宣布,用于即将推出的 C# 9.0

abstract class Animal
{
    public abstract Food GetFood();
    ...
}
class Tiger : Animal
{
    public override Meat GetFood() => ...;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-07
    • 2022-11-10
    • 2021-11-18
    • 2011-04-03
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    • 2011-02-10
    相关资源
    最近更新 更多