a.t*_*aby 14 c# generics ienumerable casting
根据这个MSDN引用 IEnumerable是协变的,这可以隐式地将对象列表转换为可枚举:
IEnumerable<String> strings = new List<String>();
IEnumerable<Object> objects = strings;
Run Code Online (Sandbox Code Playgroud)
在我自己的代码中,我编写了一行代码,当列表的项类型为class时,它是完美的Point(Point是一个简单的类,有三个属性double x,y,z):
var objects = (IEnumerable<object>)dataModel.Value;
// here property Value is a list that could be of any type.
Run Code Online (Sandbox Code Playgroud)
但是当列表的项类型为double:时,上面的代码返回以下异常:
Unable to cast object of type System.Collections.Generic.List1[System.Double]
to type System.Collections.Generic.IEnumerable1[System.Object].
Run Code Online (Sandbox Code Playgroud)
是什么区别string和double和是什么原因导致代码的工作string,但不是double?
根据这篇文章,我们可以简单地将一个列表转换为IEnumerable(没有类型参数),因为我只需要迭代项目并将新项目添加到列表中(实际上我根本不需要列出列表中的项目).我决定用这个:
var objects = (IEnumerable)dataModel.Value;
Run Code Online (Sandbox Code Playgroud)
但是如果您需要将列表中的项目投射到object并使用它们,Theodoros的答案就是您最常遵循的解决方案.
The*_*kis 21
构造类型的变体接口(例如IEnumerable<out T>)仅对于引用类型参数是变体,因为它们对超类型(例如object)的隐式转换是非表示变化的转换.这IEnumerable<string>就是协变的原因.
值类型参数的构造类型是不变的,因为它们对超类型(例如object)的隐式转换是表示变化的,这是由于需要的装箱.这就是为什么IEnumerable<double>不变的原因.
请参阅相关文档:
差异仅适用于参考类型; 如果为变量类型参数指定值类型,则该类型参数对于生成的构造类型是不变的.
可能的解决方法是使用LINQ强制转换:
var sequence = list.Cast<object>();
Run Code Online (Sandbox Code Playgroud)
这将首先检查源是否与IEnumerable<TResult>您尝试将其转换为分配兼容.
T是string,例如),它会直接返回初始源(这是理想的情况下,性能代价).T是double,例如),它将创建手动尝试转换为每个单独的元件的投影.