为什么接口实现不能返回更具体的类型?

Isa*_*avo 31 c# overloading language-design interface

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

我们举一个例子来说明:

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
{ }
Run Code Online (Sandbox Code Playgroud)

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

我可以:

  • 将返回类型更改GetFoo()IBar,或
  • 显式实现接口,只需GetBarIFoo.GetBar()方法调用即可

我真正要问的是不仅允许上面的代码编译的原因.是否有上述情况不符合规定的合同IFoo.

Jon*_*eet 20

通常,我会说这是一个平衡利益与支持这种功能的额外复杂性的情况.(所有功能都需要设计,记录,实现,测试,然后开发人员也需要了解它们.)请注意,如果您想支持返回实现接口的值类型,可能会有一些重大的复杂性,例如(因为它以不同的表示形式结束,而不仅仅是参考).

在这种情况下,我不相信 CLR甚至支持这样的功能,这将使C#很难干净地完成.

我同意这将是一个有用的功能,但我怀疑它并不足以保证所需的额外工作.

  • 乔恩,我有一个问题吗?你怎么在1分钟内写这么多? (8认同)
  • @Adriano:考虑一个派生自另一个使用显式接口实现的具体类.如果你想覆盖那个接口实现,但仍然使用原始实现,你就会遇到问题 - 你不能调用`base.Foo()`,但是转换到接口最终会递归回你的实现.它也不能与`dynamic`很好地配合. (2认同)

Mar*_*ery 6

您要问的功能称为"返回类型协方差".正如维基百科上所指出的那样,Java和C++都有它,这可能让C#没有意外.

Eric Lippert在对此答案的评论中确认此功能未实现,因为它不值得实施.(此答案的先前修订版对Eric的个人负责;他说这是不正确的,如果任何一个人负责,那就是Anders Hejlsberg.)

无论如何,现在有各种建议,将其添加到语言(见https://github.com/dotnet/roslyn/issues/357,https://github.com/dotnet/csharplang/blob/master/proposals/covariant -returns.md,https://github.com/kingces95/coreclr/issues/2),所以它可能会在未来几年内实施.根据这些讨论,听起来没有任何深刻的理由说明为什么这个特征原则上不应该存在于C# - 相反,它从来没有被判断为值得任何人努力实现.

  • 在我加入C#设计团队之前几年,该功能已添加到Java中,因此我当时没有考虑过我的意见.当我在C#设计团队工作时,在我的回忆中,设计团队从未考虑过这个问题.因此,更准确地说*安德斯*不认为值得付出努力.我不认为这是一个糟糕的功能,如果C#拥有它我会使用它.我同意有更多的功能,但我会提高优先级. (4认同)