为什么List<double>显式转换为IEnumerable<object>会抛出异常?

Why does the explicit conversion of List<double> to IEnumerable<object> throw an exception?

据此 MSDN reference IEnumerable 是协变的,这可以隐式地将对象列表转换为可枚举对象:

IEnumerable<String> strings = new List<String>();
IEnumerable<Object> objects = strings;

在我自己的代码中,我编写了一行代码,当列表的项目类型为 class Point 时,它可以完美运行(Point 是一个简单的 class,具有三个属性 double x,y,z):

var objects = (IEnumerable<object>)dataModel.Value;
// here property Value is a list that could be of any type. 

但是上面的代码returns当列表的项目类型为double时出现以下异常:

Unable to cast object of type System.Collections.Generic.List1[System.Double] 
to type System.Collections.Generic.IEnumerable1[System.Object].

stringdouble 之间有什么区别,是什么原因导致代码适用于 string 但不适用于 double

更新

根据 我们可以简单地将列表转换为 IEnumerable (没有类型参数)所以我只需要迭代项目并将新项目添加到列表中(实际上我不需要需要施放列表中的项目)。我决定使用这个:

var objects = (IEnumerable)dataModel.Value;

但是如果您需要将列表中的项目转换为 object 并使用它们,Theodoros 的答案是您最关注的解决方案。

变体接口的构造类型(例如IEnumerable<out T>)仅对引用类型参数是变体,因为它们隐式转换为超类型(例如object)是一种非表示更改转换。这就是为什么 IEnumerable<string> 是协变的。

值类型参数的构造类型是不变的,因为由于 the boxing that's required,它们到超类型(例如 object)的隐式转换是表示变化的。这就是 IEnumerable<double> 不变的原因。

参见 relevant documentation:

Variance applies only to reference types; if you specify a value type for a variant type parameter, that type parameter is invariant for the resulting constructed type.

一种可能的解决方法是使用 LINQ 转换:

var sequence = list.Cast<object>();

这将首先检查源是否与您尝试将其转换为的 IEnumerable<TResult> 赋值兼容。