如何将 IList 分配给 IList其中 T1 是 T2 的子类型
本文关键字:T2 T1 IList 类型 其中 分配 | 更新日期: 2023-09-27 18:16:03
前言:
我已经在泛型中读到过C#相当于Java的<?扩展Base的问题中有关协方差和逆变>,但是将我的项目切换到.net 4.0似乎不起作用。
请考虑以下类构造函数:
public Matrix(IList<RowVector> rows) {
if (!Vector.AreDimensionsEqual(rows)) {
throw new ArgumentException("foo");
}
for (int i = 0; i < rows.Length; ++i) {
for (int j = 0; j < rows[0].Length; ++j) {
Components[i][j] = rows[i].Components[j];
}
}
}
方法AreDimensionsEqual(IList<Vector> vectors)
:
public static bool AreDimensionsEqual(IList<Vector> vectors) {
int dimensions = vectors[0].Dimension;
for (int i = 1; i < vectors.Count; ++i) {
if (vectors[i].Dimension != dimensions) {
return false;
}
}
return true;
}
在这里,Matrix
构造函数中的rows
是RowVector
对象的列表,我尝试将其用作需要Vector
对象列表的方法调用的参数。 RowVector
是Vector
的一个亚型。
我最熟悉的是Java,所以如果我在那里编程,我会定义AreDimensionsEqual
的方法签名AreDimensionsEqual(IList<? extends Vector> vectors)
,但这种语法在C#中不可用。
我还缺少什么吗?
IListT
的泛型类型参数不是协变的。
但是 IEnumerable 给出的代码在功能上等效于问题中所示的 AreDimensionsEqual 方法。 public static bool AreDimensionsEqual(IEnumerable<Vector> vectors)
{
int dimensions = vectors.First().Dimension;
return vectors.All(v => v.Dimension == dimensions);
}
您无法执行此操作,因为IList
其泛型参数中是不变的。 作为无法执行此操作的原因的示例,请考虑以下类层次结构:
class A
{
}
class B : A
{
}
class C : A
{
}
现在想象一下以下工作:
IList<A> listOfA = new List<B>();
listOfA.Add( new C() );
我们刚刚将 C
类型的项添加到实际上属于 List<B>
类型的集合中。 我们不能那样做。 但据listOfA.Add
所知,这只是一个A
列表,C
添加到A
列表中是完全合理的事情。