无法通过基本接口使用 类 的列表

Cannot use list of classes by base interface

我的接口IDerived继承自IBase:

public IDerived : IBase { ... }

我有需要 IList 的方法:

public MyClass
{
    public static void DoSmth(IList<IBase> bases)
    { ... }
}

但尝试传递派生对象列表:

IList<IDerived> derivedObjs = ...;
MyClass.DoSmth(derivedObjs);

导致错误:

Argument type 'System.Collections.Generic.IList<IDerived> is not assignable to parameter type 'System.Collections.Generic.IList<IBase>'

我可以实现类似 'stupid' 的东西:

MyClass.DoSmth(derivedObjs.Select(d=>d as IBase).ToList());

但这听起来……不专业。

我记得几年前我遇到过类似的问题,应该通过允许 'DoSmth' 或 'MyClass' 将对象转换为基础 class... 以某种方式解决这个问题,但是找不到任何解决方案。

请告知,什么是将派生对象列表传递给期望基指向的对象列表的方法的正确方法class。

谢谢

A TSomething<TDerived> 只能分配给 TSomething<TBase>(其中 TDerived 派生自 TBase),如果 TSomethingcovariant关于它的类型参数。

一个类型在逻辑上是协变的先决条件之一是它只 returns 其类型参数的实例,并且永远不必接受它们。这是像 IEnumerable<T> 这样的只读迭代的情况,但是 而不是 IList<T> 的情况,它必须在方法中接受其类型参数类型的引用比如Add.

例如,考虑以下情况:

class Base: IBase { }
class Derived: IDerived { }
...
MyClass.DoSmth(new List<IDerived>());
...
public static void DoSmth(IList<IBase> bases)
{
    bases.Add(new Base());
}

如果编译器允许你这样做,你就会破坏类型安全,因为 Base 不是 IDerived

此处的修复取决于您在 DoSmth 中所做的事情。如果你只是迭代 bases,你应该接受一个实际上 协变的可迭代接口,即 IEnumerable<IBase>:

public static void DoSmth(IEnumerable<IBase> bases) { ... }

如果您确实需要 IList 接口支持的操作,除了将现有的 derivedObjs 更改为 IList<IBase> 或创建使用 CastToList:

的新列表
MyClass.DoSmth(derivedObjs.Cast<IBase>().ToList());