简体   繁体   中英

Storing object implementing a generic interface in a collection

I have a number of classes that are all implementing IWidget<T> interface. I would like to add them to a list, so I define something like this:

List<IWidget<T>> _widgetList; 

Here the compiler complains about the T is not being recognized:

Error 1 The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?)

Is there a way to define a list of IWidget and still keep the generic interface?

I am using .NET 3.5 SP1.

There are a few ways you can go about doing this:

1) you need a non-generic root:

public interface IWidget
{
      ...
}

public interface IWidget<T> : IWidget
{
      ...
}

so that you can use List<IWidget> _widgetList;


2) you can use dynamic s or polymorphism with contra/co-variance, but you will have to play by the rules the rules it has, <T> mustn't be a value type and you'll have to cast after accessing but not when adding, like this:

IWidget<string> xxx = ...;

var widgetListDyn = new List<IWidget<dynamic>>();
var widgetListObj = new List<IWidget<object>>();

widgetListDyn.Add(xxx);
widgetListObj.Add(xxx);

3) or you can mix the two approaches:

public interface IWidget : IWidget<object> {}

and you can use List<IWidget> _widgetList; with this technique also you'll also need a cast before a .add() :

List<IWidget> _widgetList = new List<IWidget>();
IWidget<string> xxx = ...;
IWidget xxx1 = (IWidget)xxx;

_widgetList.Add(xxx1);

4) one last way you could go about it is:

public class IWidgetList<T> : List<IWidget<T>> { }

which would be useful if you plan to have a declare a lot of the lists created in keeps you from the ugly syntax of: List<IWidget<TYPE>> and instead you can just use: IWidgetList<TYPE> and it is identical

You need to use either a non generic root interface:

public interface IWidget<T> : IWidget
{
}

or specify the type at the point of declaration:

List<IWidget<MyType>> widgetList;

Is your IWidget interface generic, ie is it actually IWidget<T>? Or just IWidget?

If it's not a generic interface, you just want the following:

public class ContainingClass
{
   List<IWidget> _widgetList;
}

If it is a generic interface, then what you need is something like this:

public class ContainingClass<T> where T : class // or some other constraint for T
{
   List<IWidget<T>> _widgetList;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM