Question regarding Generics and Inheritance
Hi
I just started working with generics and am stuck at a basic problem.
Have a base class - BaseObject
Have 3 derived classes from this - User, Product and Site.
Now, I have a ReturnObject method that returns a generic of BaseObject (List<BaseObject>)
But I really am returning List<User> from this method
This is the code from User.cs:
public List<BaseObject> ReturnObject()
{
//...do something
return List<User>;
}
So my return type is a generic of the base and I actually want to return a generic of the derived class.
Is there any way to do this ?
Also in my main program.cs, I have
List<User> u = ReturnObject()
The above line gives an error. It says that I cannot assign a generic base to a generic derived object.
Now I want to pass a collection of child and I want to declare the return type as collection of base class.
Is there anyway I can do this ???
I think I can get this done using arrays, but I would really like to use generics.
Thanks for your help
Rishi...
Answers
Hi Rishi,
The list you're returning is declared as a list of BaseObjects and you're trying to return a list of User objects (or whatever) and that's not going to work. I'd suggest creating a new list of BaseObjects and adding your User object to it. You'll then be returning List<BaseObject>, as specified in your method signature. It's a bit of a hassle and even more so when you want to be working with a list of Users outside your ReturnObject() method.
- Right, an instantiation of a generic type using a base type and a derived type does not mean those two types have an inheritance or obtain an inheritance from the relationship of the two parametrized types.
All Replies
Hi Rishi,
The list you're returning is declared as a list of BaseObjects and you're trying to return a list of User objects (or whatever) and that's not going to work. I'd suggest creating a new list of BaseObjects and adding your User object to it. You'll then be returning List<BaseObject>, as specified in your method signature. It's a bit of a hassle and even more so when you want to be working with a list of Users outside your ReturnObject() method.
- Right, an instantiation of a generic type using a base type and a derived type does not mean those two types have an inheritance or obtain an inheritance from the relationship of the two parametrized types.
Let's see if I can put together the missing pieces here.....
class BaseObject
{
abstract List<BaseObject> ReturnObject();}
class User : BaseObject
{
public List<BaseObject> ReturnObject()
{ ....... return List<User>(); }
}
This can be handle through a technique called "The Curiously Reoccuring Template Pattern":
class BaseObject<T>
{
abstract List<T> ReturnObject();}
class User : BaseObject<User>
{
public List<User> ReturnObject()
{ ....... return List<User>(); }
}
- Code Snippet
class BaseObject
{
abstract List ReturnObject();}
class User : BaseObject
{
public List ReturnObject()
{ ....... return List(); }
}
This compiles and runs but I'm not convinced it provides a realistic solution to the problem... the List returned simply is not a list of BaseObjects--for instance, we can't call User.ReturnObject () and expect to store the results in a variable typed as List<BaseObject>. If we dig a bit deeper with this code sample and try to add a second method that returns another generic list of a different type, then we end up also having to list those types in the BaseObject class definition:
Code Snippetclass BaseObject<T, U>
{
abstract List<T> ReturnObject();abstract List<U> ReturnObject();
}
Think of the maintenance headache every time the BaseObject definition changes!
Anyway, no matter how fancy we get, we can't return a generic list of base class objects and have them automatically come out the other end with their original child class type (at least not without a cast).
Here is a great link on this very topic - Covariance...
BTW - I stumbled across this topic, having just fallen for exactly the same trap. Some useful tips here too thanks all.


