说我有一系列课程:
abstract class MyClass { }
class MyFirstClass : MyClass { }
class MySecondClass : MyClass { }
class MyThirdClass : MyClass { }
我想根据这些派生类类型的可配置列表执行某些操作,因此我希望将所选类的Type
存储在列表中。我知道我可以创建一个List<Type>
,但理论上我可以将任何类添加到该列表中。另一方面,List<MyClass>
将是这些类的实例的列表,而不是类型本身的列表。我还可以创建一个enum
,其中一个值对应于每个派生类型,并且有一个工厂方法可以根据需要创建正确的值,但是当我添加{时,我必须更新至少两个以上的地方{ {1}}。
有没有办法做MyFourthClass
之类的事情?我问这个问题的事实是否意味着我的设计存在问题?
答案 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);
我一直想要这个功能很长一段时间,但我不希望它很快就会出现。