473,666 Members | 2,368 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Passing derived object of generic class to another class

Hey everyone --

Curious about some strange behaviour I'm seeing that seems to be
related to my lack of understanding on how generics work in C#. Here's
some simplified code (sorry for strange formatting) to show what my
issue is.

I have a generic abstract class here:

public abstract class MyGenericAbstra ctClass<Twhere T : MyInterface
{
//...whatever...
T _internal_inter face;
public MyGenericAbstra ctClass(T internal_var)
{
_internal_inter face = internal_var;
}
}

and I have classes that inherit from it, such as

public class MyDerived :
MyGenericAbstra ctClass<Somethi ngThatImplement sMyInterface>
{
///...whatever...
public MyDerived(Somet hingThatImpleme ntsMyInterface internal_var) :
base(internal_v ar) { }
}

My problem comes when I try to pass my "MyDerived" objects to another
class, defined as such:

public class MyBrokenClass
{
// here I have a list of MyGenericAbstra ctClass objects
private
System.Collecti ons.Generic.Lin kedList<MyGener icAbstractClass <MyInterface> >
_list_of_object s;

public void
AddMyGenericAbs tractClassToPri vateLinkedList( MyGenericAbstra ctClass<MyInter face>
object_to_add)
{
_list_of_object s.AddLast(objec t_to_add);
}
}

All of this compiles just fine.

When I try to do something like this though:
SomethingThatIm plementsMyInter face my_something = new
SomethingThatIm plementsMyInter face();

MyDerived my_derived = new MyDerived(my_so mething);
MyBrokenClass my_broken = new MyBrokenClass() ;
my_broken.AddMy GenericAbstract ClassToPrivateL inkedList(my_de rived);

Then I get a compile time error as follows:
Error 1:
The best overloaded method match for
'MyBrokenClass. AddMyGenericAbs tractClassToPri vateLinkedList( MyGenericAbstra ctClass<MyInter face>)'
has some invalid arguments

Error 2:
Argument '1': cannot convert from 'MyDerived' to
'MyGenericAbstr actClass<MyInte rface>'
So, what's the story? What have I done wrong?

Thanks kindly.
Mustafa


Jul 20 '08 #1
8 3145
On Sat, 19 Jul 2008 19:04:00 -0700, MMAS <mu***********@ gmail.comwrote:
[...]
Error 2:
Argument '1': cannot convert from 'MyDerived' to
'MyGenericAbstr actClass<MyInte rface>'
So, what's the story? What have I done wrong?
The short answer: generics aren't covariant. That is, the type parameters
have to match exactly...just having the parameters related by inheritance
isn't sufficient.

Off the top of my head, I think that if you inherited
MyGenericAbstra ctClass<MyInter faceinstead of
MyGenericAbstra ctClass<Somethi ngThatImplement sMyInterfacefor MyDerived,
that would work. At least, that is, for the specific line you're having
trouble with (I can't say whether that would fit into the design you're
trying to do).

Other solutions involving changing the way you relate the types and
instances could work as well, but without knowing more about the bigger
picture, it's hard to say.

Pete
Jul 20 '08 #2
On Jul 19, 10:14*pm, "Peter Duniho" <NpOeStPe...@nn owslpianmk.com>
wrote:
On Sat, 19 Jul 2008 19:04:00 -0700, MMAS <mustafasha...@ gmail.comwrote:
[...]
Error 2:
* *Argument '1': cannot convert from 'MyDerived' to
'MyGenericAbstr actClass<MyInte rface>'
So, what's the story? What have I done wrong?

The short answer: generics aren't covariant. *That is, the type parameters *
have to match exactly...just having the parameters related by inheritance*
isn't sufficient.

Off the top of my head, I think that if you inherited *
MyGenericAbstra ctClass<MyInter faceinstead of *
MyGenericAbstra ctClass<Somethi ngThatImplement sMyInterfacefor MyDerived,*
that would work. *At least, that is, for the specific line you're having *
trouble with (I can't say whether that would fit into the design you're *
trying to do).

Other solutions involving changing the way you relate the types and *
instances could work as well, but without knowing more about the bigger *
picture, it's hard to say.

Pete
Jul 20 '08 #3
Ah, I see. Kinda a drag -- I suppose MyGenericAbstra ct doesn't have to
be a Generic and I can just cast it's private Interface variable to
the real type when deriving from it. It just doesn't seem as nice that
way...

Thanks for the information.

On Jul 19, 10:14*pm, "Peter Duniho" <NpOeStPe...@nn owslpianmk.com>
wrote:
On Sat, 19 Jul 2008 19:04:00 -0700, MMAS <mustafasha...@ gmail.comwrote:
[...]
Error 2:
* *Argument '1': cannot convert from 'MyDerived' to
'MyGenericAbstr actClass<MyInte rface>'
So, what's the story? What have I done wrong?

The short answer: generics aren't covariant. *That is, the type parameters *
have to match exactly...just having the parameters related by inheritance*
isn't sufficient.

Off the top of my head, I think that if you inherited *
MyGenericAbstra ctClass<MyInter faceinstead of *
MyGenericAbstra ctClass<Somethi ngThatImplement sMyInterfacefor MyDerived,*
that would work. *At least, that is, for the specific line you're having *
trouble with (I can't say whether that would fit into the design you're *
trying to do).

Other solutions involving changing the way you relate the types and *
instances could work as well, but without knowing more about the bigger *
picture, it's hard to say.

Pete
Jul 20 '08 #4
On Sun, 20 Jul 2008 11:00:11 -0700, MMAS <mu***********@ gmail.comwrote:
Ah, I see. Kinda a drag -- I suppose MyGenericAbstra ct doesn't have to
be a Generic and I can just cast it's private Interface variable to
the real type when deriving from it. It just doesn't seem as nice that
way...
Well, unfortunately you haven't posted enough code for anyone else to
comment on what might be a better approach.

As one example: is there any real reason that your List<Thas to be a
List<MyGenericA bstractClass<My Interface>>? One of the reasons covariance
isn't allowed in generics is that if it is, it opens the possibility for a
generic class being used in an unsafe way. The issue the compiler doesn't
like is that if you were allowed to convert from one form of the generic
type to another, the compiler can't maintain type safety any more. But
even if the compiler allowed that, you'd still have the type safety issue.

If you don't want to do the casting, then perhaps the alternative solution
is to fix your List<Tso that it uses
MyGenericAbstra ctClass<Somethi ngThatImplement sMyInterfaceins tead of
MyGenericAbstra ctClass<MyInter face>. After all, if that's not always what
you're putting into the List<Tthen your code was broken anyway, and if
it is what you're putting into the List<T>, then changing the type should
be fine.

Of course, there's always the possibility that you're misusing generics
here anyway. The code you posted appears to have been abridged, so it's
not possible to comment on whether the rest of the generic class really
needs to be generic. But it doesn't seem to me that the part you showed
us does.

Pete
Jul 20 '08 #5
Hi again Peter -

I'm beginning to think that I do not need or even want generics in my
situation. My List<MyGenericA bstractClass<My Interface>shoul d really
become a List<MyGenericA bstractClassand MyGenericAbstra ctClass
should just have the _internal_inter face typed as MyInterface.

I'm new to Generics and thought this was a situation I could use them
to get some code-time benefits. For example, I can get strongly typed
_internal_inter face objects when I was coding my MyDerived objects.
The MyBrokenClass example, in the real code, is really a wrapper
around a collection of MyGenericAbstra ctClass objects that will be
calling a common method on all objects.

To get more detailed: my MyGenericAbstra ctClass in my real code is an
abstract "Step". The MyInterface class in my real code is the specific
arguments (StepArguments) for that step, and the MyBrokenClass is the
"StepManage r" that calls the "RunStep" method for each Step object.
Using Generics seemed a good idea to ensure that each specific
implemented step got the correct type of Arguments and also so that I
can use those arguments while coding the Step without having to do any
casting. It seems that I was wrong.

I can gladly post more code if you'd like to see how I've really
implemented all of this, but figured a short explanation would be
easier than many lines of code.

Thanks again for the help.
Mustafa

On Jul 20, 1:20*pm, "Peter Duniho" <NpOeStPe...@nn owslpianmk.com>
wrote:
Well, unfortunately you haven't posted enough code for anyone else to *
comment on what might be a better approach.

As one example: is there any real reason that your List<Thas to be a *
List<MyGenericA bstractClass<My Interface>>? *One of the reasons covariance *
isn't allowed in generics is that if it is, it opens the possibility for a *
generic class being used in an unsafe way. *The issue the compiler doesn't *
like is that if you were allowed to convert from one form of the generic *
type to another, the compiler can't maintain type safety any more. *But*
even if the compiler allowed that, you'd still have the type safety issue..

If you don't want to do the casting, then perhaps the alternative solution *
is to fix your List<Tso that it uses *
MyGenericAbstra ctClass<Somethi ngThatImplement sMyInterfaceins tead of *
MyGenericAbstra ctClass<MyInter face>. *After all, if that's not always what *
you're putting into the List<Tthen your code was broken anyway, and if *
it is what you're putting into the List<T>, then changing the type should*
be fine.

Of course, there's always the possibility that you're misusing generics *
here anyway. *The code you posted appears to have been abridged, so it's *
not possible to comment on whether the rest of the generic class really *
needs to be generic. *But it doesn't seem to me that the part you showed *
us does.

Pete
Jul 20 '08 #6
On Sun, 20 Jul 2008 12:55:29 -0700, MMAS <mu***********@ gmail.comwrote:
[...]
To get more detailed: my MyGenericAbstra ctClass in my real code is an
abstract "Step". The MyInterface class in my real code is the specific
arguments (StepArguments) for that step, and the MyBrokenClass is the
"StepManage r" that calls the "RunStep" method for each Step object.
Using Generics seemed a good idea to ensure that each specific
implemented step got the correct type of Arguments and also so that I
can use those arguments while coding the Step without having to do any
casting. It seems that I was wrong.

I can gladly post more code if you'd like to see how I've really
implemented all of this, but figured a short explanation would be
easier than many lines of code.
I have to admit, it hasn't helped me much. Your phrase "to ensure that
each specific implemented step got the correct type of Arguments" doesn't
make sense to me. If each Step sub-class uses the same interface to
define their arguments, then isn't that the "type of Arguments"? And if
so, how can a sub-class get the wrong type of Arguments?

Conversely, if each Step sub-class uses some different combination of
arguments, then in what way does having some interface used by all the
sub-classes provide something useful? Wouldn't there be arguments that
could not be represented by the interface, because of the fact that
different sub-classes are using different combinations?

Based on what you've written so far, it does seem like you're mis-using
generics. But I'm afraid I'm unable to understand the intended design
well enough to offer better advice.

I agree that "many lines of code" probably wouldn't be helpful. But as
near as I can tell, we're only talking about four different types here:
your interface, your abstract class, one example of a sub-class, and your
manager class. Surely it should be possible to put together a more
complete code sample that what you posted earlier that illustrates why
it's useful to encapsulate your arguments as an interface, as well as why
simply doing that doesn't work for your manager class (i.e. what sort of
casting winds up happening that you thought would be solved by generics?).

I would think a useful sample of 50 lines or so, perhaps even less, would
suffice. If you'd like more consideration given of your design, maybe you
can try to come up with a simplified sample like that.

Pete
Jul 20 '08 #7
I've seen the folly of my ways, as they say. I've rid myself of the
Arguments class and moved the various arguments directly into each
derived Step class. I had a "validate" method on the Arguments
interface that I was calling before each step object was run by my
StepManager (to make sure all arguments were valid for this object),
but have now made this an abstract function in my abstract base "Step"
class that is implemented in each derived class.

Like many first attempts at using something "new", I think I was using
Generics just to use them rather than using them for the right
reasons.

I have to admit, it hasn't helped me much. *Your phrase "to ensure that*
each specific implemented step got the correct type of Arguments" doesn't*
make sense to me. *If each Step sub-class uses the same interface to *
define their arguments, then isn't that the "type of Arguments"? *And if *
so, how can a sub-class get the wrong type of Arguments?

Conversely, if each Step sub-class uses some different combination of *
arguments, then in what way does having some interface used by all the *
sub-classes provide something useful? *Wouldn't there be arguments that*
could not be represented by the interface, because of the fact that *
different sub-classes are using different combinations?

Based on what you've written so far, it does seem like you're mis-using *
generics. *But I'm afraid I'm unable to understand the intended design *
well enough to offer better advice.

I agree that "many lines of code" probably wouldn't be helpful. *But as*
near as I can tell, we're only talking about four different types here: *
your interface, your abstract class, one example of a sub-class, and your*
manager class. *Surely it should be possible to put together a more *
complete code sample that what you posted earlier that illustrates why *
it's useful to encapsulate your arguments as an interface, as well as why*
simply doing that doesn't work for your manager class (i.e. what sort of *
casting winds up happening that you thought would be solved by generics?)..

I would think a useful sample of 50 lines or so, perhaps even less, would*
suffice. *If you'd like more consideration given of your design, maybe you *
can try to come up with a simplified sample like that.

Pete
Jul 21 '08 #8
On Sun, 20 Jul 2008 17:08:51 -0700, MMAS <mu***********@ gmail.comwrote:
[...]
Like many first attempts at using something "new", I think I was using
Generics just to use them rather than using them for the right
reasons.
That does happen sometimes. :)

But now, if and when you are using generics for something that could
actually benefit from them, and you run into the lack of covariance again,
at least you'll have seen the issue before and understand it. So your
effort wasn't entirely wasted. :)

Anyway, glad you got your code straightened out.

Pete
Jul 21 '08 #9

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

Similar topics

24
1736
by: Brad Marts | last post by:
I would like to have a function that takes as an argument a base class but performs differently depending on which type of derived class is passed. Can I tell which derived class is passed? For example: class Base { //... };
6
1610
by: Gernot Frisch | last post by:
I want to have a class that provides 2 methods with the same name (do1, do2) that cann be called from a function (Fkt) but Fkt does not know/care about it's type. class base { public: virtual void Do(base& b)=0; };
9
4793
by: justanotherguy63 | last post by:
Hi, I am designing an application where to preserve the hierachy and for code substitability, I need to pass an array of derived class object in place of an array of base class object. Since I am using vector class(STL), the compiler does not allow me to do this. I do realize there is a pitfall in this approach(size of arrays not matching etc), but I wonder how to get around this problem. I have a class hierachy with abstract base...
7
4742
by: Ken Allen | last post by:
I have a .net client/server application using remoting, and I cannot get the custom exception class to pass from the server to the client. The custom exception is derived from ApplicationException and is defined in an assembly common to the client and server components. The custom class merely defines three (3) constructors -- the null constructor; one with a string parameter; and one with a string and innner exception parameter -- that...
1
8328
by: Mark McDonald | last post by:
This question kind of follows on from Mike Spass’ posting 10/11/2004; I don’t understand why you can’t declare an implicit operator to convert a base class to a derived class. The text books say “neither the source nor the target types of a conversion can be a base type of the other, since a conversion would then already exist”. But this is not really true, whilst automatic (implicit) conversions do occur from the derived...
7
9558
by: Richard Grant | last post by:
Hi. In c/C++ i can pass the address of a subroutine to another subroutine as an actual parameter How do I do that in VB .NET What should be the syntax for a parameter to receive the address of a subroutine Let's say theres a sub that creates buttons and I want it to receive as a parameter the address of the sub that handles the OnClick event for the button being created How do I pass such a parameter Thanks in advance Richar
4
3140
by: Charles Churchill | last post by:
I apologize if this question has been asked before, but after about half an hour of searching I haven't been able to find an answer online. My code is beloiw, with comments pertaining to my question In short my question is why when I pass a generic type directly to the formatObject function it works fine, but when I pass it to the checkText function where it is itself a generic argument, and then it is passed to formatObject, it is seen...
11
32386
by: Frederic Rentsch | last post by:
Hi all, If I derive a class from another one because I need a few extra features, is there a way to promote the base class to the derived one without having to make copies of all attributes? class Derived (Base): def __init__ (self, base_object): # ( copy all attributes ) ...
2
4178
by: SimonDotException | last post by:
I am trying to use reflection in a property of a base type to inspect the properties of an instance of a type which is derived from that base type, when the properties can themselves be instances of types derived from that base type, or arrays or generic collections of instances of types derived from that base type. All is well until I come to the properties which are generic collections, I don't seem to be able to find an elegant way of...
0
8440
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, well explore What is ONU, What Is Router, ONU & Routers main usage, and What is the difference between ONU and Router. Lets take a closer look ! Part I. Meaning of...
0
8355
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8781
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
6191
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupr who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5662
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4193
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4365
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
2006
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
2
1769
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.