简体   繁体   中英

Is List<System.Type> that accepts only certain types possible?

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.

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.

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.

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.

您可以为List指定任何类型,所以是:

List<IMyClass> myClassList = new List<IMyClass>();

You can try using generics like this:

 class EmployeeList<T> where T : IMyClass
 {
     // ...
 }

是 - 将其List<IMyClass>然后您可以存储实现该接口的任何实例。

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 ie compile time time checkings, intellisense and all other type cheking tools provided by Visual Studio and C# compiler

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