Visual C# Developer Center > Visual C# Forums > Visual C# Language > Question regarding Generics and Inheritance
Ask a questionAsk a question
 

AnswerQuestion regarding Generics and Inheritance

  • Wednesday, May 23, 2007 10:34 PMRishi Jhaver Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    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

  • Thursday, May 24, 2007 1:28 AMmichhes Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    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.  

  • Thursday, May 24, 2007 2:52 PMPeter RitchieMVP, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    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

  • Thursday, May 24, 2007 1:28 AMmichhes Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    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.  

  • Thursday, May 24, 2007 2:52 PMPeter RitchieMVP, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    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.
  • Friday, May 25, 2007 7:46 PMJames Curran Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    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>();  }

    }

  • Monday, May 28, 2007 7:34 AMmichhes Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

     

    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 Snippet

    class 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).

  • Monday, June 04, 2007 12:56 PMStu4 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    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.