Covariant return types

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Why are there still no covariant return types?

All searches reveal no workarounds accept for using an interface which is a
real pain. I wind up missing this capability almost every time I inherit a
class. The best workaround and one that I use is the new keyword and cast
the base class reference, but in my opinion this is a bad practice leading to
error prone code.

Can someone from MS chime in on this and provide some feedback?

Thanks,

Mike
 
miked said:
Why are there still no covariant return types?

All searches reveal no workarounds accept for using an interface which is
a
real pain. I wind up missing this capability almost every time I inherit
a
class. The best workaround and one that I use is the new keyword and cast
the base class reference, but in my opinion this is a bad practice leading
to
error prone code.

Can someone from MS chime in on this and provide some feedback?
I'm not MS, far from it, but here's a link to an MS webpage with a
semi-official position on covariant return types:

http://lab.msdn.microsoft.com/produ...edbackid=dbd59c0f-226f-4274-b655-71ecd52d1840

"Postponed"

Andrew
 
And here's another nugget, from
http://msdn.microsoft.com/chats/transcripts/vstudio/vstudio_092304.aspx:

Host: peterhal (Microsoft)
Q: Why doesn't C# allow Covariant Return Types?
(http://weblogs.asp.net/okloeten/archive/2004/04/24/119580.aspx)
A: Overrides in C# are just reimplementation of base members. They do not
participate in member lookup or overload resolution. As such, variance in
the override implementation would not be available from the callsite on the
derived object without significant (breaking) changes to our member lookup
rules.


Not sure I quite understand what they are saying - does the override method
somehow poke itself where the base method was? Time to look at some MSIL.

Andrew
 
Andrew,

Thanks for the links and info...

I have read before that covariant return types are not necessary which I
guess is true but to get around the lack of covariant return types you have
3 options assuming class A : B

1) Use and interface
- Klunky / Bloated / Alot of work
+ None

2) public new B AProperty { get { (B)base.AProperty;} }
- Uneccesary Casting / Runtime Errors
+ Best solution if one day we get covariant return types or explicit
class member declaration

3) public override A AProperty { get { return this.BProperty; } }
public B BProperty { get { return this._bProperty } }
private B _b;
- What a mess this is and will require a lot of rewriting if covariant
return types are one day allowed.

Maybe MS could at least provide explicit member declarations for classes as
shown below, still messy, works like an interface without having to code an
interface just to make up for the lack of covariant return types.

public override A A.AProperty { get { return base.AProperty; } }
public B AProperty { get { return base.AProperty; } }

Or... Maybe I simply don't understand OOP programming and inheritance if so
I wish someone would set me straight as I literally hit the covariant return
type wall almost every day.

Thanks,

Mike
 
I agree that covariant return types are gold. I use them in C++, my main
language, all the time. I remember the sigh of relief when VC++ finally
supported it.

I'm hoping that the C# guys will find a way to make covariance work and
until then I think your new/cast method is the best workaround.

Andrew
 
And it's a pity no one told the folks who wrote the WinForms DataGrid
which *requires* covariant returns for one feature. (with an empty
collection, it will base the column headings by getting the data type
of the return value of the Item property(Indexer) of it's DataSource.
However, the data source at that point is an IList, and IList defines
the return value of Item a Object.)
 
miked said:
I have read before that covariant return types are not necessary which I
guess is true but to get around the lack of covariant return types you have

Lost of things are in C# that are not "necessary": foreach, lock, using,
yield-return, ... and a lot more are coming in C#3.

They're dead-handy though, and so is co-variant return-types.
3 options assuming class A : B

1) Use and interface
- Klunky / Bloated / Alot of work

And, it doesn't solve any typing issues, it simply moves them.
+ None

2) public new B AProperty { get { (B)base.AProperty;} }
- Uneccesary Casting / Runtime Errors

a. The cast is not necessary for co-variant returns, it's necessary
because you have (type-wise) unexpressed knowledge that in this instance
base.AProperty should be not only A, but B.

b. A runtime-error would show that your unexpressed knowledge is false
+ Best solution if one day we get covariant return types or explicit
class member declaration

3) public override A AProperty { get { return this.BProperty; } }
public B BProperty { get { return this._bProperty } }
private B _b;
- What a mess this is and will require a lot of rewriting if covariant
return types are one day allowed.

Not to mention that A may still have storage reserved for a now unused
AProperty, all in all -- not really text-book inheritance.
Maybe MS could at least provide explicit member declarations for classes as
shown below, still messy, works like an interface without having to code an
interface just to make up for the lack of covariant return types.

public override A A.AProperty { get { return base.AProperty; } }
public B AProperty { get { return base.AProperty; } }

I'm not sure I like that very much. I think i prefer that Properties of
objects stay the same no matter what static-type I know the origin
object as, so

B b = /* some B */
A a = b;
a.AProperty == b.AProperty;

but not nessesarily:

typeof(a.AProperty) == typeof(b.AProperty)
Or... Maybe I simply don't understand OOP programming and inheritance if so
I wish someone would set me straight as I literally hit the covariant return
type wall almost every day.

I use the:

T new P { get { return (T) base.P; } }

in-between, and it works very well for me.

Be aware that this pattern requires a corresponding "set" in the
base-class is counter-variant, and should be virtual - if it exists. The
object can then verify that it's assertion on base.P.GetType() isn't
violated.

One of the reasons that co/counter-variant support isn't included is
that in order to utilize it, without making mistakes, you need to think
quite a bit.
 
Back
Top