假设我有:
class A {
//field, properties and common methods
}
class B : A {
//specific ones
}
class C : A {
//specific ones
}
class D : A {
//specific ones
}
然后是这 3 个列表:
List<B> b_list = new List<B>();
List<C> c_list = new List<C>();
List<D> d_list = new List<D>();
我需要一个指向b_list
、c_list
和d_list
的列表。考虑到类B,C,D具有相同的超类A,是否有可能?
像这样:
List<A>[] lists = new[] {b_list, c_list, d_list};
谢谢
你想把List<B>
、List<C>
和List<D>
视为List<A>
的子类,但它们不是。 他们唯一共同的超型是object
。
在 .NET 4 及更高版本中,您可以将这些类型全部引用转换为 IEnumerable<A>
,因为IEnumerable<out T>
接口在 T
中是协变的。 在 .NET 4.5 中,又添加了两个协变接口:IReadOnlyList<out T>
和 IReadOnlyCollection<out T>
,因此您也可以将它们视为 IReadOnlyList<A>
和 IReadOnlyCollection<A>
。 其中一个接口可能适合您的需求。
类在 .NET 中不能协变,并且接口只能在类型参数中协变,前提是该类型参数仅用于"输出"位置。 换句话说,该方法IList<T>.Add(T item)
防止IList<>
协变。
因此,您可以这样做,假设 .NET 4.5:
IReadOnlyList<A>[] lists = new[] {b_list, c_list, d_list};
在 .NET 4 中,您可以执行此操作,这不太有用,但可能足以满足您的需求:
IEnumerable<A>[] lists = new[] {b_list, c_list, d_list};
不直接(协方差"限制")
但你可以做到
List<A> superTypeList =
b_array.Cast<A>()
.Concat(c_array.Cast<A>())
.Concat(d_array.Cast<A>())
.ToList();
你必须列出一个 A 列表,并为其分配 b、c、d 对象。您必须将子类对象强制转换为父类 A。这将造成限制,您将只能访问从基类继承的属性和方法等。
List<B> blist = new List<B>();
List<C> cList = new List<C>();
List<D> dList = new List<D>();
List<List<A>> arrays = new List<List<A>>();
arrays.Add(b_array.ConvertAll(c=>(A)c));;
更好的方法是使用称为复合模式的设计模式。
实质上,您创建一个基类(组件),其中包含您希望子节点(如果它们又有子节点,则为组合节点,如果它们停止分支,则为叶节点)的所有方法,然后仅实现您希望每个子节点在每个子类型中使用的方法。
在您的情况下,您可以这样做:
abstract class A {
//All methods for all classes
//ex.
public abstract void b();
public abstract void c();
public abstract void d();
}
class B : A {
public override void b()
{
//Do Something
}
public override void c()
{
throw new Exception("Not Implemented");
}
public override void d()
{
throw new Exception("Not Implemented");
}
}
class C : A {
public override void b()
{
throw new Exception("Not Implemented");
}
public override void c()
{
//Do Something
}
public override void d()
{
throw new Exception("Not Implemented");
}
}
class D : A {
public override void b()
{
throw new Exception("Not Implemented");
}
public override void c()
{
throw new Exception("Not Implemented");
}
public override void d()
{
//Do Something
}
}
然后,根据多态定律,如果您执行以下操作,则应保留派生类(b,c,d等)的方法。
List<B> blist = new List<B>();
List<C> cList = new List<C>();
List<D> dList = new List<D>();
List<List<A>> arrays = new List<List<A>>();