Jed
Jed

Reputation: 10877

How to work with a Generic List of a Generic Type in a Generic Class

In the example console app below, you will notice that the program is attempting to create a basketball team and, then, add a player and a coach to the team.

The design of the application implements generic classes (Team and Person) which concrete classes (Lakers(), Player(), and Coach()) will inherit.

The program throws build exceptions at the point where I attempt to add the Person object to the team.Members list.

The exception reads:

The best overloaded method match for 'System.Collections.Generic.List>.Add(Person)' has some invalid arguments.

I don't understand why the compiler doesn't allow me to add the generic Player (Kobe and Phil) to the Members list when Members is defined as a generic list of a generic Player.

Can you explain the cause of the error and how to work around it?

Also, can you fill me in on whether or not the example program below is not typically how we should be implementing generics? In other words, given the errors in the program below, it makes me wonder why I should implement generics and not stick with a normal abstract class.

By the way, please don't down-vote simply because you don't like the Lakers ;)

class Program
    {
        static void Main(string[] args)
        {
            //Create a team
            Team<Lakers> team = new Lakers();

            //Create a player then add the player to the list of team members
            Person<Player> p = new Player();
            p.Name = "Kobe";
            team.Members.Add(p); //Invalid argument exception here

            //Create a coach then add the coach to the list of team members
            Person<Coach> c = new Coach();
            c.Name = "Phil";
            team.Members.Add(c); //Invalid argument exception here

            //Display the members of the team
            team.Members.ForEach(n => Console.WriteLine(n.Name));
            Console.ReadLine();
        }
    }

    //A generic class containing a generic list of a generic type
    abstract class Team<T>
    {
        public List<Person<T>> Members = new List<Person<T>>();
    }

    //A concrete basketball team
    class Lakers : Team<Lakers>
    {
    }

    //A generic class that represents a person
    abstract class Person<T>
    {
        public string Name { get; set; }
    }

    //A concrete person that represents a basketball player
    class Player : Person<Player>
    {
    }

    //A concrete person that represents a basketball coach
    class Coach : Person<Coach>
    {
    }

Upvotes: 0

Views: 566

Answers (3)

Geoff
Geoff

Reputation: 9340

Because you declare Team as type Lakers and Person as type Player. Those are not equal.

Do you need to constrain your List with ? Can't you just declare it as Person?

abstract class Team<T>
    {
        public List<Person> Members = new List<Person>();
    }

Upvotes: 1

Lucero
Lucero

Reputation: 60190

You seem to be mixing up inheritance and generics. While technically different, you can see a generic class as template, and not as an is-a relationship. Normal inheritance is all you want here.

Upvotes: 1

Jakub Konecki
Jakub Konecki

Reputation: 46008

Why not just:

//An abstract class that represents a person
    abstract class Person
    {
        public string Name { get; set; }
    }

    //A concrete person that represents a basketball player
    class Player : Person
    {
    }

    //A concrete person that represents a basketball coach
    class Coach : Person
    {
    }

The usage of generics seems totally unnecessary. the simple hierarchy should be enough for you.

Upvotes: 1

Related Questions