By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,086 Members | 1,875 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,086 IT Pros & Developers. It's quick & easy.

What can I do about Covariant return types?

P: n/a
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 abstract new System.Data.IDbConnection Connection [ get, set ]
}

and I am forced to implement:

public __gc class MyCommand : public IDbCommand
{
__property IDbConnection* get_Connection();
__property void set_Connection(IDbConnection* value);
}

instead of what I really want, which is:

public __gc class MyCommand : public IDbCommand
{
__property MyConnection* get_Connection();
__property void set_Connection(MyConnection* value);
}

This has been an annoyance in that consumers of my library have to cast
things to the derived types in order to use them. But it is turning into a
MAJOR PROBLEM now that I am doing Visual Studio.NET integration. VS.NET
bases design time behavior (such as code generation) on the types of
components/properties and thier attributes. I have had several cases where
I can not get VS.NET to read my attributes because it thinks it has an
IDbConnection instead of a MyConnection.

Are there any workarounds at all to the covariant return type problem?
Thanks!

-Steve
Nov 16 '05 #1
Share this Question
Share on Google+
13 Replies


P: n/a
Stephen,
Unfortunately I'm not sure how to in C++, I wanted to let you know how to in
C# or VB.NET, in case it offers some hints for you to pursue.

In C# you use "Explicit interface member implementations"

http://msdn.microsoft.com/library/de...pec_13_4_1.asp

In VB.NET you can change the name of the implementing function and make it
private to get the same effect as C#.

I have not delved deep enough into C++ yet to know how here.

Hope this helps
Jay

"Stephen Walch" <sw****@proposion.com> wrote in message
news:OB**************@tk2msftngp13.phx.gbl...
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 abstract new System.Data.IDbConnection Connection [ get, set ] }

and I am forced to implement:

public __gc class MyCommand : public IDbCommand
{
__property IDbConnection* get_Connection();
__property void set_Connection(IDbConnection* value);
}

instead of what I really want, which is:

public __gc class MyCommand : public IDbCommand
{
__property MyConnection* get_Connection();
__property void set_Connection(MyConnection* value);
}

This has been an annoyance in that consumers of my library have to cast
things to the derived types in order to use them. But it is turning into a MAJOR PROBLEM now that I am doing Visual Studio.NET integration. VS.NET
bases design time behavior (such as code generation) on the types of
components/properties and thier attributes. I have had several cases where I can not get VS.NET to read my attributes because it thinks it has an
IDbConnection instead of a MyConnection.

Are there any workarounds at all to the covariant return type problem?
Thanks!

-Steve

Nov 16 '05 #2

P: n/a
"Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in message
news:es**************@TK2MSFTNGP10.phx.gbl...
Stephen,
Unfortunately I'm not sure how to in C++, I wanted to let you know how to in
C# or VB.NET, in case it offers some hints for you to pursue.

In C# you use "Explicit interface member implementations"


Managed C++ does not support explicit interface implementation, and the CLR
does not support covariant return. In C#, you can use explicit interface
implementation to simulate covariant return, but it is a dirty hack, and your
class will become unusable as a base class for Managed C++ users.

Unfortunately there is not a good solution to the OP's question while
remaining in Managed C++. Probably the least painful solution would be to
write the classes that use pseudo-covariant return in C#. Managed C++ should
still be able to consume those classes, even if you can't derive off of them.

Ken
Nov 16 '05 #3

P: n/a
Ken,
your class will become unusable as a base class for
Managed C++ users.
Will Managed C++ have the same issue with VB.NET classes that make the
implementing function private? I know at the IL level the C# & VB.NET
technique are slightly different, while having the same net effect.

Out of curiosity why is it that Managed C++ cannot derive from them? I
realize that the method of the interface itself is now hidden, I would not
expect that to preclude you from inheriting from it.

Thanks
Jay

"Ken Alverson" <US********@Alverson.net> wrote in message
news:O5*************@TK2MSFTNGP11.phx.gbl... "Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in message news:es**************@TK2MSFTNGP10.phx.gbl...
Stephen,
Unfortunately I'm not sure how to in C++, I wanted to let you know how to in C# or VB.NET, in case it offers some hints for you to pursue.

In C# you use "Explicit interface member implementations"
Managed C++ does not support explicit interface implementation, and the

CLR does not support covariant return. In C#, you can use explicit interface
implementation to simulate covariant return, but it is a dirty hack, and your class will become unusable as a base class for Managed C++ users.

Unfortunately there is not a good solution to the OP's question while
remaining in Managed C++. Probably the least painful solution would be to
write the classes that use pseudo-covariant return in C#. Managed C++ should still be able to consume those classes, even if you can't derive off of them.
Ken

Nov 16 '05 #4

P: n/a
Can you tell me more about this "dirty hack"? I do not minf making my
classes final; I just want managed applications that use my library to see
the more-derived returned types. Can you give me an example, perhaps based
on my original problem. Deriving from:

public abstract interface IDbCommand
{
public abstract new System.Data.IDbConnection Connection [ get, set ]
}

what I want clients to see:

public __gc class MyCommand : public IDbCommand
{
__property MyConnection* get_Connection();
__property void set_Connection(MyConnection* value);
}

Thanks again.

"Ken Alverson" <US********@Alverson.net> wrote in message
news:O5*************@TK2MSFTNGP11.phx.gbl...
"Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in message news:es**************@TK2MSFTNGP10.phx.gbl...
Stephen,
Unfortunately I'm not sure how to in C++, I wanted to let you know how to in C# or VB.NET, in case it offers some hints for you to pursue.

In C# you use "Explicit interface member implementations"
Managed C++ does not support explicit interface implementation, and the

CLR does not support covariant return. In C#, you can use explicit interface
implementation to simulate covariant return, but it is a dirty hack, and your class will become unusable as a base class for Managed C++ users.

Unfortunately there is not a good solution to the OP's question while
remaining in Managed C++. Probably the least painful solution would be to
write the classes that use pseudo-covariant return in C#. Managed C++ should still be able to consume those classes, even if you can't derive off of them.
Ken

Nov 16 '05 #5

P: n/a
Stephen,
I believe the "dirty hack" that Ken was referring to is what C# does, which
is specific to C#.

C# hides the implementation of the IDbCommand.Connection method, then you
can define Connection property with the return type you want.

I want to say the closest thing in C++ would be ATL's tear-off interface,
although I never did really figure out how those work. Also I'm not sure you
can do a tear-off interface in Managed C++.

Hope this helps
Jay

"Stephen Walch" <sw****@proposion.com> wrote in message
news:uQ**************@TK2MSFTNGP12.phx.gbl...
Can you tell me more about this "dirty hack"? I do not minf making my
classes final; I just want managed applications that use my library to see
the more-derived returned types. Can you give me an example, perhaps based on my original problem. Deriving from:

public abstract interface IDbCommand
{
public abstract new System.Data.IDbConnection Connection [ get, set ] }

what I want clients to see:

public __gc class MyCommand : public IDbCommand
{
__property MyConnection* get_Connection();
__property void set_Connection(MyConnection* value);
}

Thanks again.

"Ken Alverson" <US********@Alverson.net> wrote in message
news:O5*************@TK2MSFTNGP11.phx.gbl...
"Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in

message
news:es**************@TK2MSFTNGP10.phx.gbl...
Stephen,
Unfortunately I'm not sure how to in C++, I wanted to let you know how to in C# or VB.NET, in case it offers some hints for you to pursue.

In C# you use "Explicit interface member implementations"


Managed C++ does not support explicit interface implementation, and the

CLR
does not support covariant return. In C#, you can use explicit interface implementation to simulate covariant return, but it is a dirty hack, and

your
class will become unusable as a base class for Managed C++ users.

Unfortunately there is not a good solution to the OP's question while
remaining in Managed C++. Probably the least painful solution would be to write the classes that use pseudo-covariant return in C#. Managed C++

should
still be able to consume those classes, even if you can't derive off of

them.

Ken


Nov 16 '05 #6

P: n/a
"Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in message
news:OA****************@tk2msftngp13.phx.gbl...
Ken,
your class will become unusable as a base class for
Managed C++ users.
Will Managed C++ have the same issue with VB.NET classes that make the
implementing function private? I know at the IL level the C# & VB.NET
technique are slightly different, while having the same net effect.


I honestly don't know, but I would suspect the effect would be the same.
Out of curiosity why is it that Managed C++ cannot derive from them? I
realize that the method of the interface itself is now hidden, I would not
expect that to preclude you from inheriting from it.


Well, specifically, you can't override the pseudo-covariant function (which is
generally why you derived in the first place). I believe you could derive
from the pseudo-covariant class if you didn't try to override any
pseudo-covariant functions.

If you try to override the generic version of the function, you'll get this
error:

C2555: 'Derived::Clone': overriding virtual function return type differs and
is not covariant from 'Base::Clone'.

If you try to override the specific version of the function, you'll instead
get this error:

C2392: 'Base __gc *Derived::Clone(void)' : covariant returns types are not
supported in managed types.

I wouldn't be surprised if the next version of MC++ makes one or the other of
these scenarios work, but that's a ways off from now...

Ken
Nov 16 '05 #7

P: n/a
"Stephen Walch" <sw****@proposion.com> wrote in message
news:uQ**************@TK2MSFTNGP12.phx.gbl...
Can you tell me more about this "dirty hack"? I do not minf making my
classes final; I just want managed applications that use my library to see
the more-derived returned types. Can you give me an example, perhaps based
on my original problem. Deriving from:

public abstract interface IDbCommand
{
public abstract new System.Data.IDbConnection Connection [ get, set ]
}

what I want clients to see:

public __gc class MyCommand : public IDbCommand
{
__property MyConnection* get_Connection();
__property void set_Connection(MyConnection* value);
}


You'll have to write the MyCommand class in C#. Then you can do:

public class MyCommand : IDbCommand {
IDbConnection IDbCommand.Connection {
get {...}
set {...}
}
public MyConnection Connection {
get {...}
set {...}
}
}

This implements the IDbCommand's Connection property, while not exposing it to
users of your class (unless they cast you to your IDbCommand interface).
Then, with the IDbCommand version hidden, you are creating a new property with
your new signature that returns your MyConnection type.

Ken
Nov 16 '05 #8

P: n/a
"Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in message
news:ej**************@TK2MSFTNGP12.phx.gbl...

I'm not sure you
can do a tear-off interface in Managed C++.


You could sort of simulate a tear-off interface in the CLR by defining an
implicit conversion from your class to the interface which will be torn-off,
and when that implicit conversion occurs, you could create an internal object
that implements the interface and return it.

The wrinkle in that plan is the torn-off interface cannot be casted back to
the original object. Whether or not that is sufficient for what you are
attempting to do is another issue.

Ken
Nov 16 '05 #9

P: n/a
Ken,
Well, specifically, you can't override the pseudo-covariant function (which is generally why you derived in the first place). I believe you could derive
from the pseudo-covariant class if you didn't try to override any
pseudo-covariant functions. O.K. so if I'm reading you correctly its the 'same' problem, you can not
make the derived functions type more specific then the base functions type.
In other words Covariant return types are just not supported in any of the
..NET languages. Not sure if IL itself supports it or not. I understand there
is a 'redirection' method that Eiffel uses to achieve it.

What I normally do is meet 'half way', the function in the abstract base
class has a more specific type then the interface, while all the functions
in the derived classes have the same return type as the abstract base class
function.

Thanks for the info
Jay

"Ken Alverson" <US********@Alverson.net> wrote in message
news:uJ**************@TK2MSFTNGP09.phx.gbl... "Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in message news:OA****************@tk2msftngp13.phx.gbl...
Ken,
your class will become unusable as a base class for
Managed C++ users.
Will Managed C++ have the same issue with VB.NET classes that make the
implementing function private? I know at the IL level the C# & VB.NET
technique are slightly different, while having the same net effect.


I honestly don't know, but I would suspect the effect would be the same.
Out of curiosity why is it that Managed C++ cannot derive from them? I
realize that the method of the interface itself is now hidden, I would not expect that to preclude you from inheriting from it.


Well, specifically, you can't override the pseudo-covariant function

(which is generally why you derived in the first place). I believe you could derive
from the pseudo-covariant class if you didn't try to override any
pseudo-covariant functions.

If you try to override the generic version of the function, you'll get this error:

C2555: 'Derived::Clone': overriding virtual function return type differs and is not covariant from 'Base::Clone'.

If you try to override the specific version of the function, you'll instead get this error:

C2392: 'Base __gc *Derived::Clone(void)' : covariant returns types are not supported in managed types.

I wouldn't be surprised if the next version of MC++ makes one or the other of these scenarios work, but that's a ways off from now...

Ken

Nov 16 '05 #10

P: n/a
"Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in message
news:OF**************@TK2MSFTNGP10.phx.gbl...

O.K. so if I'm reading you correctly its the 'same' problem, you can not
make the derived functions type more specific then the base functions type.
In other words Covariant return types are just not supported in any of the
.NET languages. Not sure if IL itself supports it or not. I understand there
is a 'redirection' method that Eiffel uses to achieve it.


Almost, but it's worse than that.

If your base class uses explicit interface implementation to simulate
covariant return, you *can not* override that function in Managed C++. I'm
not saying you can't override it covariantly, you can't override at all. If
you try to override it covariantly, you get a message saying covariant return
isn't supported on managed types. If you try to override it non-covariantly,
you get a message complaining that your return type was contravariant from the
return type of your pseudo-covariant parent.

It's a catch-22.

Ken
Nov 16 '05 #11

P: n/a
Ken,
If your base class uses explicit interface implementation to simulate
covariant return, you *can not* override that function in Managed C++. I get it, it does sound like a bug in the way Managed C++ is interpreting
the base class from C#.

As I don't have a problem from C#, or in VB.NET when I use the VB.NET
method.

I wonder if Whidbey is going to offer anything for this.

Thanks for the info
Jay

"Ken Alverson" <US********@Alverson.net> wrote in message
news:Oc*************@TK2MSFTNGP10.phx.gbl... "Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in message news:OF**************@TK2MSFTNGP10.phx.gbl...

O.K. so if I'm reading you correctly its the 'same' problem, you can not
make the derived functions type more specific then the base functions type. In other words Covariant return types are just not supported in any of the .NET languages. Not sure if IL itself supports it or not. I understand there is a 'redirection' method that Eiffel uses to achieve it.
Almost, but it's worse than that.

If your base class uses explicit interface implementation to simulate
covariant return, you *can not* override that function in Managed C++.

I'm not saying you can't override it covariantly, you can't override at all. If you try to override it covariantly, you get a message saying covariant return isn't supported on managed types. If you try to override it non-covariantly, you get a message complaining that your return type was contravariant from the return type of your pseudo-covariant parent.

It's a catch-22.

Ken

Nov 16 '05 #12

P: n/a
Yes, C++ in Whidbey is going to support the CLR feature of explicit
interface implementations. Current plan is to offer the fully general
functionality of VB in that respect (but we think with nicer syntax).

Ronald Laeremans
Visual C++ team

"Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in message
news:uT**************@TK2MSFTNGP09.phx.gbl...
Ken,
If your base class uses explicit interface implementation to simulate
covariant return, you *can not* override that function in Managed C++. I get it, it does sound like a bug in the way Managed C++ is interpreting
the base class from C#.

As I don't have a problem from C#, or in VB.NET when I use the VB.NET
method.

I wonder if Whidbey is going to offer anything for this.

Thanks for the info
Jay

"Ken Alverson" <US********@Alverson.net> wrote in message
news:Oc*************@TK2MSFTNGP10.phx.gbl...
"Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in

message
news:OF**************@TK2MSFTNGP10.phx.gbl...

O.K. so if I'm reading you correctly its the 'same' problem, you can not make the derived functions type more specific then the base functions type. In other words Covariant return types are just not supported in any of the .NET languages. Not sure if IL itself supports it or not. I understand there is a 'redirection' method that Eiffel uses to achieve it.


Almost, but it's worse than that.

If your base class uses explicit interface implementation to simulate
covariant return, you *can not* override that function in Managed C++.

I'm
not saying you can't override it covariantly, you can't override at all.

If
you try to override it covariantly, you get a message saying covariant

return
isn't supported on managed types. If you try to override it

non-covariantly,
you get a message complaining that your return type was contravariant

from the
return type of your pseudo-covariant parent.

It's a catch-22.

Ken


Nov 16 '05 #13

P: n/a
It worked! I had to play around with it a bit to find the right C++
syntax. Here is what I ended up with:

private:
IDbConnection* IDbCommand::get_Connection();
void IDbCommand::set_Connection(IDbConnection* value);
public:
[ MyAttributes ]
__property MyConnection* get_Connection();
__property void set_Connection(MyConnection* value);

Note that I had to remove "__property" from the interface implementations. I
could compile with them there, by client C# code complained that they could
not access the property.

Thanks for the support. You saved me from having to implement a complete
set of C# wrapper classes as my public interface!

-Steve

----- Original Message -----
From: "Ken Alverson" <US********@Alverson.net>
Newsgroups: microsoft.public.dotnet.languages.vc
Sent: Thursday, October 23, 2003 4:54 PM
Subject: Re: What can I do about Covariant return types?

"Stephen Walch" <sw****@proposion.com> wrote in message
news:uQ**************@TK2MSFTNGP12.phx.gbl...
Can you tell me more about this "dirty hack"? I do not minf making my
classes final; I just want managed applications that use my library to see the more-derived returned types. Can you give me an example, perhaps based on my original problem. Deriving from:

public abstract interface IDbCommand
{
public abstract new System.Data.IDbConnection Connection [ get, set ] }

what I want clients to see:

public __gc class MyCommand : public IDbCommand
{
__property MyConnection* get_Connection();
__property void set_Connection(MyConnection* value);
}
You'll have to write the MyCommand class in C#. Then you can do:

public class MyCommand : IDbCommand {
IDbConnection IDbCommand.Connection {
get {...}
set {...}
}
public MyConnection Connection {
get {...}
set {...}
}
}

This implements the IDbCommand's Connection property, while not exposing

it to users of your class (unless they cast you to your IDbCommand interface).
Then, with the IDbCommand version hidden, you are creating a new property with your new signature that returns your MyConnection type.

Ken

Nov 16 '05 #14

This discussion thread is closed

Replies have been disabled for this discussion.