Why C# Doesn't Allow Inheritance of Return Type When Implementing an Interface

Why C# doesn't allow inheritance of return type when implementing an Interface

UPDATE: This answer was written in 2009. After two decades of people proposing return type covariance for C#, it looks like it will finally be implemented; I am rather surprised. See the bottom of https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/ for the announcement; I'm sure details will follow.


This feature is called "return type covariance". C# does not support it for the following reasons:

1) The CLR doesn't support it. To make it work in C#, we'd have to just spit a whole bunch of little helper methods that do casts on the return type to the right thing. There's nothing stopping you from doing that yourself.

2) Anders believes that return type covariance is not a good language feature.

3) \We have lots of higher priorities for the language. We have only limited budgets and so we try to only do the best features we can in any given release. Sure, this would be nice, but it's easy enough to do on your own if you want to. Better that we spend the time adding features that improve the developer experience or add more representational power to the language.

Inheriting an interface with a refined return type

To answer your questions:

why doesn't [x] typecheck, but [y] does?

Simply because C# (and the CLR) don't support return type covariance. (Eric Lippert is the best source you can get for an answer to a question like "Why doesn't C# do X?")

Is there any way the two can behave observably different behaviour?

No. You're correct in thinking that this should meet the contract.

A property getter that returns a Child theoretically meets the "returns a Parent" contract.

However, the fact remains that C# (and the CLR) don't support this. You know it meets the "returns a Parent" contract, but you can't tell C# that.


As an alternative implementation to your second example, you could use explicit interface implementation:

class MyClass : MyInterface
{
Parent MyInterface.P { get { return this.P; } }
public Child P { get; set; }
}

Implemented like this,

  • whenever you use an instance of MyClass, the contract you see and can use is that it can accept or return a Child
  • whenever you cast that instance to MyInterface, the contract you can see and use is only that it can return a Parent.

Edit: What this gains you over your working example is that if P is actually a sensible property name (that makes sense for both the Parent property in the interface and the Child property in the implementation), you can use it for both.

Why can't an interface implementation return a more specific type?

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.

Why restricting return type for method and property inheritance so that descendants are not allowed?

I think feature you are looking for is name Covariant Return Type

As to "why" is it not implemented, noone knows. IMO this feature is not so needed, so it is simply not implemented.

And especialy in your case it can be easily solved using Explicit Interface Implementation

Interface not implemented when Returning Derived Type

Unfortunately, the return type must match. What you are looking for is called 'return type covariance' and C# doesn't support that.

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=90909

Eric Lippert, senior developer on C# Compiler team, mentions on his blog that they don't plan to support return type covariance.

"That kind of variance is called
"return type covariance". As I
mentioned early on in this series, (a)
this series is not about that kind of
variance, and (b) we have no plans to
implement that kind of variance in C#.
"

http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx

It's worth reading Eric's articles on covariance and contravariance.

http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx

C# Property that returns interface type when accessed through an interface, and concrete type when accessed through concrete class

You need to add explicit interface implementation in CA.

public CA: IA
{
public CB B { get; }
IB IA.B { get => B; }
}


Related Topics



Leave a reply



Submit