为什么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].
string
和 double
之间有什么区别,是什么原因导致代码适用于 string
但不适用于 double
?
更新
根据 我们可以简单地将列表转换为 IEnumerable
(没有类型参数)所以我只需要迭代项目并将新项目添加到列表中(实际上我不需要需要施放列表中的项目)。我决定使用这个:
var objects = (IEnumerable)dataModel.Value;
但是如果您需要将列表中的项目转换为 object
并使用它们,Theodoros 的答案是您最关注的解决方案。
变体接口的构造类型(例如IEnumerable<out T>
)仅对引用类型参数是变体,因为它们隐式转换为超类型(例如object
)是一种非表示更改转换。这就是为什么 IEnumerable<string>
是协变的。
值类型参数的构造类型是不变的,因为由于 the boxing that's required,它们到超类型(例如 object
)的隐式转换是表示变化的。这就是 IEnumerable<double>
不变的原因。
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>
赋值兼容。
- 如果它是赋值兼容的(例如
T
是 string
的情况),it will return the initial source directly(这是性能方面的理想情况)。
- 如果它与赋值不兼容(例如,您发现
T
是 double
的情况),it will create a projection that attempts the conversion manually for each individual element.
据此 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].
string
和 double
之间有什么区别,是什么原因导致代码适用于 string
但不适用于 double
?
更新
根据 IEnumerable
(没有类型参数)所以我只需要迭代项目并将新项目添加到列表中(实际上我不需要需要施放列表中的项目)。我决定使用这个:
var objects = (IEnumerable)dataModel.Value;
但是如果您需要将列表中的项目转换为 object
并使用它们,Theodoros 的答案是您最关注的解决方案。
变体接口的构造类型(例如IEnumerable<out T>
)仅对引用类型参数是变体,因为它们隐式转换为超类型(例如object
)是一种非表示更改转换。这就是为什么 IEnumerable<string>
是协变的。
值类型参数的构造类型是不变的,因为由于 the boxing that's required,它们到超类型(例如 object
)的隐式转换是表示变化的。这就是 IEnumerable<double>
不变的原因。
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>
赋值兼容。
- 如果它是赋值兼容的(例如
T
是string
的情况),it will return the initial source directly(这是性能方面的理想情况)。 - 如果它与赋值不兼容(例如,您发现
T
是double
的情况),it will create a projection that attempts the conversion manually for each individual element.