Ian Boyd
Ian Boyd

Reputation: 256671

How do i add items to a generic collection?

Given:

public static void DoStuff<T>(ICollection<T> source)
{
    Customer c = new Customer();
    ....
    source.Add(c);
}

except c is not of type <T>.

So how do i add an item to a generic collection?


i tried having:

public static void DoStuff(ICollection<Human> source)
{
    Customer c = new Customer();
    ....
    source.Add(c);
}

but i don't use it because nobody can call DoStuff:

ICollection<Customer> c;
DoStuff(c); <---error

because something about covariance, and .NET doesn't realize that Customer descends from Human:

class Customer : Human {}

Upvotes: 3

Views: 5610

Answers (3)

James Michael Hare
James Michael Hare

Reputation: 38397

Just so you know why you get that error, an ICollection<Customer> can not be passed to an ICollection<Human> because they are not the same thing. Think of it this way, if you had an ICollection<Human> you could Add(new Deadbeat()) if Deadbeat derived from Human.

The other answers on ways to avoid your issue with a generic solves your problem (so they should get the answer credit):

public static void DoStuff<T>(ICollection<T> source) where T : new()
{
    T c = new T();
    ...
    source.Add(c);
}

but I just wanted to throw this answer out to explain why you get that error. Think of it, if you could pass a collection of Customer as a collection of Human, it would let you add ANY kind of human, and this would violate the original collection.

Thus, even though Customer extends Human, this does not mean that ICollection<Customer> extends ICollection<Human> and ICollection<T> is not covariant/contravariant because it uses T for both in and out operations.

Upvotes: 8

That Chuck Guy
That Chuck Guy

Reputation: 463

You probably want something like this:

public static void DoStuff<T>(ICollection<T> source)
    where T : new()
{
    T c = new T();
    source.Add(c);
}

Upvotes: 1

BrokenGlass
BrokenGlass

Reputation: 160882

should be just:

T t = new T();
....
source.Add(t);

Also you will have to add the new constraint to guarantee that T has a public parameterless constructor:

public static void DoStuff<T>(ICollection<T> source) where T: new()
{
   //...
}

Upvotes: 7

Related Questions