Is List that accepts only certain types po

2020-07-23 08:36发布

is there any possibility to have a generic List<System.Type> and to have a constraint on the type? I want to store types in a list for a lookup, but only types where the class of this type implements a specific interface.

Something like this:

List<Type> : where typeof(Type) is IMyClass

Is that possible? If not do you have any suggestion on how to solve this issue?

Any help appreciated !

EDIT:

Sorry I haven't been clearer on the subject, but Sign's comment below is correct, I don't have instances available, just types.

Assume the following:

class PluginA : IPlugin { } 
class PluginB : IPlugin { } 
class PluginC : ISomeOtherInterface { } 

var pluginTypes = new List<Type>()
pluginTypes.Add(typeof(PluginA) --> OK
pluginTypes.Add(typeof(PluginB) --> OK
pluginTypes.Add(typeof(PluginC) --> should fail

Yes I could wrap this, but hoped that there would be a better variant which checks during compiletime or hints with intellisense what types are allowed.

标签: c#
7条回答
家丑人穷心不美
2楼-- · 2020-07-23 08:57

if I understood you correctly, you want a list of System.Type which checks that its elements implement a certain interface. This is easy to accomplish. Just implement IList<Type> by wrapping most the List<Type> functionality and add a couple of checkups.

public class TypeFilteredList : IList<Type>
{
    private Type filterType;
    private List<Type> types = new List<Type>();

    public TypeFilteredList(Type filterType)
    {
        this.filterType = filterType;
    }

    private void CheckType(Type item)
    {
        if (item != null && !filterType.IsAssignableFrom(item))
            throw new ArgumentException("item");
    }

    public void Add(Type item)
    {
        CheckType(item);
        types.Add(item);
    }

    public void Insert(int index, Type item)
    {
        CheckType(item);
        types.Insert(index, item);
    }

...

}

this code will work for base classes as well as interfaces.

Example usage:

TypeFilteredList list = new TypeFilteredList(typeof(IInterface));
list.Add(typeof(Implementation));
list.Add(typeof(int)); // ArgumentException

If you however don't need IList functionality, you can implement IEnumerable<Type> or ISet<Type> (wrapping HashSet<T>). List leaves an option to add the same type several times, which it seems to me is something, you don't want.

查看更多
萌系小妹纸
3楼-- · 2020-07-23 08:58

You can specify any type for the List, so yes:

List<IMyClass> myClassList = new List<IMyClass>();
查看更多
霸刀☆藐视天下
4楼-- · 2020-07-23 09:04

Okay, I normally wouldn't do this (the answer is so trivial), but as nobody has suggested the most obvious answer... Inheritance.

public sealed class IMyClassList : List<IMyClass> { }

Done and done.

查看更多
相关推荐>>
5楼-- · 2020-07-23 09:10

Well you could write your own wrapper:

public class ConstrainedList<T> where T : IMyClass
{
    private List<T> list;

    // Access the list however you want
}

You can't add constraints to List<T> itself though.

You might want to expose the wrapped list directly, or you might want to implement IList<T> and just delegate each member to the list. It's hard to say without knowing more about what you're trying to achieve.

查看更多
ゆ 、 Hurt°
6楼-- · 2020-07-23 09:16

I see only one way to check it at compile time. You can create class derived from the List and write custom generic Add method to do it.

Something like this:

class PlugginsList : List<Type>
{
  public void Add<T>()
    where T : IPlugin
  {
    Add(typeof(T));
  }
}

var plugginList = new PlugginsList();
plugginList.Add<PluginA>() --> OK
plugginList.Add<PluginB>() --> OK
plugginList.Add<PluginC>() --> will fail

You will achive all your goals by using generic method i.e. compile time time checkings, intellisense and all other type cheking tools provided by Visual Studio and C# compiler

查看更多
相关推荐>>
7楼-- · 2020-07-23 09:22

Yes - make it a List<IMyClass> then you can store any instance that implements that interface.

查看更多
登录 后发表回答