Why can't an interface implementation return a

2019-02-16 05:00发布

问题:

If an interface specifies a property or method to return another interface, why is it not allowed for implementations of the first interface to "change" the return type into a more specific type?

Let's take an example to illustrate:

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
{ }

I know how to make it work, that's not my concern.

I can just either:

  • Change return type of GetFoo() to IBar, or
  • Explicitly implement the interface and just call GetBar from the IFoo.GetBar() method

What I am really asking is the reasoning for not just allowing the code above to compile. Is there any case where the above doesn't fulfill the contract specified by IFoo.

回答1:

Usually, I'd say that it would be a case of balancing the benefit against the added complexity of supporting such a feature. (All features take effort to design, document, implement, test, and then developers need to be educated about them too.) Note that there could be some significant complexities if you wanted to support returning a value type which implemented an interface, for example (as that ends up in a different representation, rather than just a reference).

In this case, I don't believe the CLR even supports such a feature, which would make it very hard for C# to do so cleanly.

I agree it would be a useful feature, but I suspect it hasn't been deemed useful enough to warrant the extra work required.



回答2:

The feature you're asking about is called "return type covariance". As noted on Wikipedia, Java and C++ both have it, which perhaps makes it surprising that C# does not.

Eric Lippert confirms in the comments on this answer that this feature wasn't implemented because it wasn't deemed worth the implementation effort. (A previous revision of this answer assigned responsibility for that decision to Eric personally; he says that this is incorrect, and that if any one person is responsible it was Anders Hejlsberg.)

Regardless, there are now various proposals to add it to the language (see 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), so perhaps it will get implemented in the next couple of years. Per those discussions, it doesn't sound like there are any profound reasons why the feature shouldn't exist in C# in principle - rather, it's just never so far been judged worth anyone's effort to implement.