views:

239

answers:

6

So I have an object, lets say Item<U>. I want to create a(n) (I)List<T> containing a collection of these items. The problem that I am running into is that the collection of Item<U> can have any number of different types for U in them.

What I can not figure out is the signature to use for the IList. I tryed IList<Item<T>>, but because I do not (in the class where the IList is to be used) have a defination of T (which as I said varys anyhow) I can not use this signature. What is the best way to approach this requirement?

+1  A: 

You can make your method generic, like:

public void DoSomethingWithTheList<T>(IList<Item<T>> theList)
{
    //Do that something
}
klausbyskov
A: 

You could try this

class Item<U>
{
   ...
}


class Item : Item<object> {
   ...
}

....
IList<Item> itemList;
Daniel A. White
You still can't put an Item<int> and and Item<string> into itemList. Normally you'd do class Item {} class Item<T> : Item { } to make this work.
Eric Lippert
A: 

I think you just want an IList<Item<U>>. The key is that the T in the name of the generic type IList<T> is just a placeholder - it doesn't have any special meaning. You want a list of Item<U>s, so just make one.

Now, this will of course mean that the method / class that contains this IList will itself be generic in U, but that seems to be dictated by the terms of your question.

AakashM
+5  A: 

You need to add a non-generic interface to your Item<U> and make the collection out of those interfaces.

There is no way you can create a collection of IList<Item<T>> where T is some base type for a lot of different object types you want to place into the same list. This is co(ntra)-variance in place which specifically prohibits this.

So you need to instead add something common, that isn't generic, and make the list out of that. For instance, you might make Item<T> implement IItem, and create IList<IItem> instead.

That's the best you can do.

Lasse V. Karlsen
This seems to be the cleanist way to accomplish what I need. For some reason, it just did not come to me. Thanks.
David Williams
+2  A: 

An IList is meant to hold a single type. To decide if something is a "single type" or not, you have to expand all the type parameters. Taking your example of an IList<Item<T>>, the T would have to be one and only one thing for a particular instance.

For example, you can pick Animal for T and then proceed to put Dog, Cat, and Bear instances in the IList. But you can't put arbitrary types there; they have to be able to be converted to the type you specify for T. And if your types are and not related in this way, you don't have any choice except to have a non-generic interface for your list. You could also consider defining an interface type for T that all your eligible items can conform to.

Once you've decided what T will be, you can then make your method generic:

public void PrintItems<T>(IList<Item<T>> list)
{
  // ...
}
John Feminella
+1  A: 

Its a bit of a pain in .Net 3, because all the Item for different U are treated as independent types. To make it work you have to manually introduce an interface for this type:

interface IItem{}

class Item<U>:IItem {...}

and now you can:

IList<IItem> list = new IList<IItem>();
list.Add(new Item<string>());
list.Add(new Item<int>());

Alternatively you could stick to the non-generic list.

Grzenio