列表与LT;>特定的类类型

时间:2014-09-21 02:33:40

标签: c# generics inheritance

说我有一系列课程:

abstract class MyClass { }
class MyFirstClass : MyClass { }
class MySecondClass : MyClass { }
class MyThirdClass : MyClass { }

我想根据这些派生类类型的可配置列表执行某些操作,因此我希望将所选类的Type存储在列表中。我知道我可以创建一个List<Type>,但理论上我可以将任何类添加到该列表中。另一方面,List<MyClass>将是这些类的实例的列表,而不是类型本身的列表。我还可以创建一个enum,其中一个值对应于每个派生类型,并且有一个工厂方法可以根据需要创建正确的值,但是当我添加{时,我必须更新至少两个以上的地方{ {1}}。

有没有办法做MyFourthClass之类的事情?我问这个问题的事实是否意味着我的设计存在问题?

2 个答案:

答案 0 :(得分:2)

你想要的是一个通用的类型列表(List<Type>)但是就像你说的那样,你可以在那里插入任何类型。我可以给你的解决方案是从MyClass实现你自己的类型列表,例如:

class TypeMyClassList : IList<Type>
{
    private readonly List<Type> _list = new List<Type>();

    private bool CheckType(Type type)
    {
        return type.IsSubclassOf(typeof (MyClass)) || typeof (MyClass) == type;
    }

    public IEnumerator<Type> GetEnumerator()
    {
        return _list.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public void Add(Type item)
    {
        if (CheckType(item))
            _list.Add(item);
        else
            throw new InvalidOperationException("You can't add other types than derived from A");
    }

    public void Clear()
    {
        _list.Clear();
    }

    public bool Contains(Type item)
    {
        return _list.Contains(item);
    }

    public void CopyTo(Type[] array, int arrayIndex)
    {
        _list.CopyTo(array, arrayIndex);
    }

    public bool Remove(Type item)
    {
        return _list.Remove(item);
    }

    public int Count
    {
        get { return _list.Count; }
    }

    public bool IsReadOnly { get { return false; } }

    public int IndexOf(Type item)
    {
        return _list.IndexOf(item);
    }

    public void Insert(int index, Type item)
    {
        if (!CheckType(item))
            throw new InvalidOperationException("You can't insert other types than derived from A");
        _list.Add(item);
    }

    public void RemoveAt(int index)
    {
        _list.RemoveAt(index);
    }

    public Type this[int index]
    {
        get
        {
            return _list[index];
        }
        set
        {
            Insert(index, value);
        }
    }
}

然后你可以按照你想要的那样思考:

    var typeMyClassList = new TypeMyClassList
        {
            typeof(MyClass),
            typeof(MyClassA),
            typeof(MyClassB)
        };

糟糕的是它会允许在编译时执行此操作(错误将在运行时引发):

var typeMyClassList = new TypeMyClassList
        {
            typeof(MyClass),
            typeof(MyClassA),
            typeof(MyClassB),
            typeof(string)
        };

答案 1 :(得分:1)

使用静态编译时类型检查无法做到这一点。您最好的选择是使用RaulOtaño这样的解决方案,您可以在运行时进行检查。

你为什么不能这样做?原因是C#缺少静态元类类型。元类是类的类。换句话说,元类的实例本身就是类。如果C#有元类,你可以说像IList<MyClassMeta>(或者语法可能是IList<meta MyClass>,编译器只允许你将MyClass(或它的子类)作为“实例”传递,例如,< / p>

IList<meta MyClass> list;
list.Add(MyClass);

我一直想要这个功能很长一段时间,但我不希望它很快就会出现。