473,385 Members | 1,693 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Why are there no covariant return types?

Hi,

this code does not compile in C#:

class base_class {}
class derived_class : base_class {}

class A
{
public virtual base_class f()
{
return new base_class();
}
}

class B : A
{
public override derived_class f() // covariant return type
{
return new derived_class();
}
}
Are there any plans to support covariant return types (and maybe
parameter types???) in upcoming C# versions? It could make some OO
designs so much simpler...
Stefan
Nov 16 '05 #1
14 1982
Stefan Slapeta <st************@slapeta.com> wrote:

<snip>
Are there any plans to support covariant return types (and maybe
parameter types???) in upcoming C# versions? It could make some OO
designs so much simpler...


I haven't tried it, but I wouldn't be surprised if covariant return
types became available in C#v2, along with generics - I believe in the
Java world, generics made covariance just drop out naturally.

You could always download the .NET v2 beta and try it :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #2
Hi Stefan,

Frankly I don't see any use of that.

imagin if you have method like this

void Foo(A a)
{
XXX res = a.f();
}

How can you possibly know what XXX should be. The only sure thing is that
XXX == base_class.
In the current version of C# if you use deriv_class as XXX the compiler will
wmit an error in compile type. With covariant return types it cannot do that
and the error will show up at run time.

So what you and up is code like

base_class res = a.f();
if(res is deriv_class)
{
type cast and use deriv class
}
else
{
use base class
}

or some of its variants. Which is almost what we have now, but imagin if
there is deeper hierarcy.

Or you can use something like
deriv_class res;
try
{
res = a.f()
}
catch(invlid type case exception)
{
}

which is...
You can do that with generics because actually you don't need to use
inheritance and virtual methods, but rather you generate a new type.
--

Stoitcho Goutsev (100) [C# MVP]
"Stefan Slapeta" <st************@slapeta.com> wrote in message
news:cb**********@paperboy.Austria.EU.net...
Hi,

this code does not compile in C#:

class base_class {}
class derived_class : base_class {}

class A
{
public virtual base_class f()
{
return new base_class();
}
}

class B : A
{
public override derived_class f() // covariant return type
{
return new derived_class();
}
}
Are there any plans to support covariant return types (and maybe
parameter types???) in upcoming C# versions? It could make some OO
designs so much simpler...
Stefan

Nov 16 '05 #3
Stoitcho Goutsev (100) [C# MVP] wrote:
Frankly I don't see any use of that.
This concept (covariance) is supported by a wide range of programming
languages and opens a wide range of possibilities in OO design.
imagin if you have method like this

void Foo(A a)
{
XXX res = a.f();
}

How can you possibly know what XXX should be. The only sure thing is that
XXX == base_class.
Yes, this amount of knowledge is the fundamental idea of what is named
'polymorphism'.
In the current version of C# if you use deriv_class as XXX the compiler will
wmit an error in compile type. With covariant return types it cannot do that
and the error will show up at run time.


No, it will not, of course. It's the same as

BaseClass bc = new Derived();

I just wonder why this quite simple concept is not implemented in C#:
IMO it _must_ be implemented in the CIL (at least in 2.0) because
covariant return types supported by C++.

Stefan
Nov 16 '05 #4
Could you give us some real life example of where you could use that.
And frankly I don't see how c++ supports that. I would say that c++ may not
check the return type when overriding methods, but to support it I really
doubt it.

Would you say that c# supports covariant return types if it doesn't report
an error? Because honestly I don't see what more it can you do about it.
Yes, you may say that the CLR supports covariant return types because it
simply doesn't check the type of the return value for method overriding and
overloading.
--

Stoitcho Goutsev (100) [C# MVP]
"Stefan Slapeta" <st************@slapeta.com> wrote in message
news:cb**********@paperboy.Austria.EU.net...
Stoitcho Goutsev (100) [C# MVP] wrote:
Frankly I don't see any use of that.


This concept (covariance) is supported by a wide range of programming
languages and opens a wide range of possibilities in OO design.
imagin if you have method like this

void Foo(A a)
{
XXX res = a.f();
}

How can you possibly know what XXX should be. The only sure thing is that XXX == base_class.


Yes, this amount of knowledge is the fundamental idea of what is named
'polymorphism'.
In the current version of C# if you use deriv_class as XXX the compiler will wmit an error in compile type. With covariant return types it cannot do that and the error will show up at run time.


No, it will not, of course. It's the same as

BaseClass bc = new Derived();

I just wonder why this quite simple concept is not implemented in C#:
IMO it _must_ be implemented in the CIL (at least in 2.0) because
covariant return types supported by C++.

Stefan

Nov 16 '05 #5
Stoitcho Goutsev (100) [C# MVP] wrote:
Could you give us some real life example of where you could use that.
And frankly I don't see how c++ supports that. I would say that c++ may not
check the return type when overriding methods, but to support it I really
doubt it.


ok, here is a living example in C++ which is not implementable in C#. I
think it explaines itself, if not, just compile and debug it. For
further information where this makes sense: http://tinyurl.com/2s6zp

#include <iostream>

class base {
public:
virtual void g() const {
std::cout << "base" << std::endl;
}
};
class derived : public base {
public:
virtual void g() const {
std::cout << "derived" << std::endl;
}
};

class A {
base m_base;
public:
virtual base const& f() {
return m_base;
}
};

class B : public A {
derived m_derived;
public:
virtual derived const& f() {
return m_derived;
}
};

void some_function(A& a)
{
a.f().g();
}

int main()
{
B b;
some_function(b);
}

Nov 16 '05 #6
See there is my point if you change in class B the method *f* to return
*base* isnted of derived the result will be the same. So you have no
advantages using covariant return types.

As it goes for the example you post. Those are not managed classes. From the
CLR perspective (if you use ILDasm you can see) those are value types and
are not releated with any inheritance.

If you make them managed classes (*__gc*) and fix all the errors that the
compiler reports you will end up with one error # C2392 that says:

'method' : covariant returns types are not supported in managed types

Anyways I still don't see any advantage using them. Anything, but
porortunity for a bug to creep into my release version.
--

Stoitcho Goutsev (100) [C# MVP]
"Stefan Slapeta" <st************@slapeta.com> wrote in message
news:cb**********@paperboy.Austria.EU.net...
Stoitcho Goutsev (100) [C# MVP] wrote:
Could you give us some real life example of where you could use that.
And frankly I don't see how c++ supports that. I would say that c++ may not check the return type when overriding methods, but to support it I really doubt it.


ok, here is a living example in C++ which is not implementable in C#. I
think it explaines itself, if not, just compile and debug it. For
further information where this makes sense: http://tinyurl.com/2s6zp

#include <iostream>

class base {
public:
virtual void g() const {
std::cout << "base" << std::endl;
}
};
class derived : public base {
public:
virtual void g() const {
std::cout << "derived" << std::endl;
}
};

class A {
base m_base;
public:
virtual base const& f() {
return m_base;
}
};

class B : public A {
derived m_derived;
public:
virtual derived const& f() {
return m_derived;
}
};

void some_function(A& a)
{
a.f().g();
}

int main()
{
B b;
some_function(b);
}

Nov 16 '05 #7
Stoitcho Goutsev (100) [C# MVP] <10*@100.com> wrote:
Could you give us some real life example of where you could use that.


Here's a *really* simple example: ICloneable.

ICloneable defines Clone's return type to be object, when actually you
almost *always* end up casting the result to the type you know it will
be - the same type as the instance you're calling it on.

So, if I want to clone an ArrayList, I need:

ArrayList copy = (ArrayList) original.Clone();

If ArrayList could have declared

ArrayList Clone()
{
....
}

we wouldn't need to do this.

Now in fact, this *is* done all over the framework already, using
explicit interface implementation - look at the various database
classes (SqlConnection, SqlCommand etc). It's a nasty hack around the
lack of covariant return types, and it would have been much nicer if a
single method could have been declared, instead of one for the generic
version and one for the concrete subtype.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #8
Yeah, besides the fact that theoretically you don't know the type of the
object, which Clone methods you call.

And again in theory one should go with the most generic base type and then
do the conversion.

---
Stoitcho Goutsev (100) [C# MVP]
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Stoitcho Goutsev (100) [C# MVP] <10*@100.com> wrote:
Could you give us some real life example of where you could use that.


Here's a *really* simple example: ICloneable.

ICloneable defines Clone's return type to be object, when actually you
almost *always* end up casting the result to the type you know it will
be - the same type as the instance you're calling it on.

So, if I want to clone an ArrayList, I need:

ArrayList copy = (ArrayList) original.Clone();

If ArrayList could have declared

ArrayList Clone()
{
...
}

we wouldn't need to do this.

Now in fact, this *is* done all over the framework already, using
explicit interface implementation - look at the various database
classes (SqlConnection, SqlCommand etc). It's a nasty hack around the
lack of covariant return types, and it would have been much nicer if a
single method could have been declared, instead of one for the generic
version and one for the concrete subtype.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 16 '05 #9

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Stefan Slapeta <st************@slapeta.com> wrote:

<snip>
Are there any plans to support covariant return types (and maybe
parameter types???) in upcoming C# versions? It could make some OO
designs so much simpler...


I haven't tried it, but I wouldn't be surprised if covariant return
types became available in C#v2, along with generics - I believe in the
Java world, generics made covariance just drop out naturally.


Java actually uses a different mechanism for covariants, one that's so
simple that the generated bytecode works in JVMs back to (at least) 1.3,
though the 1.5 compiler is the first to allow the syntax.

class Base { Object foo() { ...} }
class Derived extends Base { String foo() {...} }

is compiled as if Derived also defined a method

Object foo() { return String-version-of-foo(); }

This makes the dispatch of Base.foo() do the right thing.
Nov 16 '05 #10
Stoitcho Goutsev (100) [C# MVP] wrote:
Yeah, besides the fact that theoretically you don't know the type of the
object, which Clone methods you call.

And again in theory one should go with the most generic base type and then
do the conversion.


In theory, you should avoid any cast if possible because every cast is a
potential runtime error!

And here - *with* covariant return types - you *for sure* know what
class you are dealing with *and* you can avoid any cast.

ArrayList original;
ArrayList copy = original.Clone();
Stefan
Nov 16 '05 #11
Stoitcho Goutsev (100) [C# MVP] wrote:

'method' : covariant returns types are not supported in managed types

And so I would be interested whether they are supported in C# 2.0; I
think they _are_ in the C++.net release.
Anyways I still don't see any advantage using them. Anything, but
porortunity for a bug to creep into my release version.


I think there you have not understood this concept so far: using
covariant return types _can not_ lead to errors you don't also get
without them!

Stefan
Nov 16 '05 #12
Stoitcho Goutsev (100) [C# MVP] wrote:
See there is my point if you change in class B the method *f* to return
*base* isnted of derived the result will be the same. So you have no
advantages using covariant return types.


I know what you mean - maybe the example was not the best. Covariant
return types of coure only make sense if you deal *not only* with the
base class (or any interface), but also with the (return types of the)
derived class. Jon's example maybe provides the best possible explanation.

Stefan
Nov 16 '05 #13
On Fri, 02 Jul 2004 11:38:49 +0200, Stefan Slapeta
<st************@slapeta.com> wrote:
And so I would be interested whether they are supported in C# 2.0; I
think they _are_ in the C++.net release.


Hi Stefan:

Putting the code from your original post into Beta 1 of the 2005
compiler produces:

'Testt.B.f()': return type must be 'Test.base_class' to match
overridden member 'Test.A.f()'

--
Scott
http://www.OdeToCode.com
Nov 16 '05 #14
Hmm, there are always cases where something can be useful. I said in theory
becuse I can't see any possible way to know what is the type in this
situation

void Foo(ArrayList list)
{
XXX copy = list.Clone();

//What is XXX? The simple answer is ArrayList. But is it?

}

A dont see many cases where you create a list and cloned. Normaly you
received as a parameter or it is property of some object. In this case you
cannot know.
--

Stoitcho Goutsev (100) [C# MVP]
"Stefan Slapeta" <st************@slapeta.com> wrote in message
news:cc**********@paperboy.Austria.EU.net...
Stoitcho Goutsev (100) [C# MVP] wrote:
Yeah, besides the fact that theoretically you don't know the type of the
object, which Clone methods you call.

And again in theory one should go with the most generic base type and then do the conversion.


In theory, you should avoid any cast if possible because every cast is a
potential runtime error!

And here - *with* covariant return types - you *for sure* know what
class you are dealing with *and* you can avoid any cast.

ArrayList original;
ArrayList copy = original.Clone();
Stefan

Nov 16 '05 #15

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

13
by: Stephen Walch | last post by:
Error C2392 is hitting me hard! I have a managed C++ library that implements a bunch of fixed interfaces. For example, one interface is: public abstract interface IDbCommand { public...
2
by: Mike | last post by:
I keep running into the scenario below over and over again. Currently I get around not having covariant return types by using an interface and explicit property definitions which works to some...
6
by: Hasani | last post by:
When implementing .net interfaces in vc++.net, is there anyway to get around the "error C2392: : covariant returns types are not supported in managed types" error? I know how to do this in c#. Is...
16
by: Bob Hairgrove | last post by:
Consider the classic clone() function: class A { public: virtual ~A() {} virtual A* clone() const = 0; }; class B : public A { public:
6
by: miked | last post by:
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...
8
by: Alex Vinokur | last post by:
Here is a code from http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.8 -------------------------------------- class Shape { public: virtual ~Shape() { } // A...
3
by: kikazaru | last post by:
Is it possible to return covariant types for virtual methods inherited from a base class using virtual inheritance? I've constructed an example below, which has the following structure: Shape...
2
by: Sebastian Schucht | last post by:
Hi, I have a templateclass with virtual member-functions, so i can't create instances ... but for returning the result i would like use one. So i replaced the A<TTypefrom the baseclass with the...
9
by: Rahul | last post by:
Hi Everyone, I was trying to implement covariant return types and i get a compilation error, class BB : public AA { }; class A
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.