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 aChild
- whenever you cast that instance to
MyInterface
, the contract you can see and use is only that it can return aParent
.
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
How to Detect a Process Start & End Using C# in Windows
MVC Web API: No 'Access-Control-Allow-Origin' Header Is Present on the Requested Resource
What Are Best Practices for Using Smtpclient, Sendasync and Dispose Under .Net 4.0
Adding Headers When Using Httpclient.Getasync
Return JSON with Error Status Code MVC
Query Microsoft Access Mdb Database Using Linq and C#
Does C# Support Multiple Inheritance
The Type '...' Has No Constructors Defined
How to Delete a Registry Value in C#
Why Are Subjects Not Recommended in .Net Reactive Extensions
How to Use Interface as a C# Generic Type Constraint
Get the Property, as a String, from an Expression<Func<Tmodel,Tproperty>>
Convert Dictionary<String, Object> to Anonymous Object
Multi-Select Dropdown List in ASP.NET
How to Turn Off or Handle Camelcasing in JSON Response ASP.NET Core