如何将 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构造函数中的rowsRowVector对象的列表,我尝试将其用作需要Vector对象列表的方法调用的参数。 RowVectorVector的一个亚型。

我最熟悉的是Java,所以如果我在那里编程,我会定义AreDimensionsEqual的方法签名AreDimensionsEqual(IList<? extends Vector> vectors),但这种语法在C#中不可用。

我还缺少什么吗?

如何将 IList<T1> 分配给 IList<T2>其中 T1 是 T2 的子类型

IListT的泛型类型参数不是协变的。

但是 IEnumerable public static bool AreDimensionsEqual(IEnumerable<Vector> vectors) { int dimensions = vectors.First().Dimension; return vectors.All(v => v.Dimension == dimensions); }

给出的代码在功能上等效于问题中所示的 AreDimensionsEqual 方法。

您无法执行此操作,因为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列表中是完全合理的事情。