我更喜欢使用 IEnumerable<object>
,因为 LINQ 扩展方法在其上定义,而不是 IEnumerable
,这样我就可以使用,例如,range.Skip(2)
.但是,我也更喜欢使用 IEnumerable
, 对于 T[]
可隐式转换为 IEnumerable
是否T
是引用类型还是值类型。对于后一种情况,不涉及拳击,这很好。结果,我可以做到 IEnumerable range = new[] { 1, 2, 3 }
.将两个世界的优点结合起来似乎是不可能的。反正我选择安家IEnumerable
并在我需要应用 LINQ 方法时进行某种转换。
来自 this SO线程,我开始知道range.Cast<object>()
能够胜任这项工作。但它会产生性能开销,我认为这是不必要的。我尝试执行像 (IEnumerable<object>)range
这样的直接编译时转换.根据我的测试,它适用于引用元素类型但不适用于值类型。有什么想法吗?
仅供引用,问题源于 this GitHub 问题。而我使用的测试代码如下:
static void Main(string[] args)
{
// IEnumerable range = new[] { 1, 2, 3 }; // won't work
IEnumerable range = new[] { "a", "b", "c" };
var range2 = (IEnumerable<object>)range;
foreach (var item in range2)
{
Console.WriteLine(item);
}
}
最佳答案
According to my tests, it works for reference element type but not for value type.
正确。这是因为 IEnumerable<out T>
是协变的,并且co-variance/contra-variance is not supported for value types .
I come to know that range.Cast() is able to do the job. But it incurs performance overhead which is unnecessary in my opinion.
IMO 如果你想要一个对象集合和给定的值类型集合,那么性能成本(由装箱带来)是不可避免的。使用非通用 IEnumerable
不会避免拳击因为IEnumerable.GetEnumerator
提供一个 IEnumerator
谁的.Current
属性返回 object
.我宁愿总是使用 IEnumerable<T>
而不是 IEnumerable
.所以只需使用 .Cast
方法而忘记拳击。
关于c# - 从 IEnumerable 转换为 IEnumerable<object>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38451939/