仅在 3.5 中从 List<T> 到 IEnumerable<T> 的 InvalidCastException

InvalidCastException from List<T> to IEnumerable<T> only in 3.5

如果我这样称呼

var list = new List<Class1>();
Test((IEnumerable<Interface1>)list);

public interface Interface1
{

}

public static void Test(IEnumerable<Interface1> test)
{

}

public class Class1 : Interface1
{

}

我在 3.5 框架中遇到 InvalidCastException,但在 4 和 4.5 中没问题。而且我不明白为什么,两者都有 IEnumerable

如果我检查 3.5 和 4.5 中的列表,我不明白为什么会收到 InvalidCastException

4.5:

public class List<T> : IList<T>, ICollection<T>, 
    IEnumerable<T>, IEnumerable, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>

3.5:

public class List<T> : IList<T>, ICollection<T>, 
    IEnumerable<T>, IList, ICollection, IEnumerable

在 3.5 中,IEnumerable<T> 接口不是协变的。这是在 4.0 中添加的。

需要协方差才能转换为更派生的类型,这里就是这种情况(List<T> 实现 IEnumerable<T>)。

MSDN

您假设 IEnumerable<T> 是协变的,这在 .NET 4.0 中才成立。在旧版本中,它不是协变的(因为该语言不支持该功能)。

这是因为在 3.5 中 IEnumerable<T> 被声明为

public interface IEnumerable<T> : IEnumerable

但在 4.0 及更新版本中它被声明为

public interface IEnumerable<out T> : IEnumerable

out 允许 covariance,这是您需要从 List<Class1>();IEnumerable<Interface1>

在 3.5 中你只能做 List<Class1>();IEnumerable<Class1>List<Interface1>();IEnumerable<Interface1>


作为 3.5 中的解决方法,您可以使用 Cast<T>() LINQ 方法完成您想要的。

var list = new List<Class1>();
Test(list.Cast<Interface1>());