因此,我了解C#
中最常见的集合都实现了IEnumerable<T>
界面:List<T>
,T[]
和Dictionary<TKey,TVal>
都是这样做的。
但是,当您运行LINQ查询时,例如:
myCol.Where(myBoolMethod);
您将返回的数据作为实现IEnumerable<T>
的未知类型。
因此,我想知道这些数据是如何实际存储的,直到您通过.ToList()
,.ToArray()
等将其转换为更有用的格式。
它是否仍然属于源类型?它是否存储在伪数组中?它是上述的某种组合吗?
除此之外,是否有任何理由为什么转换为一种IEnumerable<T>
总是比转换为另一种更快 - 即myCol.Where(myBoolMethod).ToArray()
总是比myCol.Where(myBoolMethod).ToList()
更快无论涉及哪种数据类型?
答案 0 :(得分:5)
它不是存储。它表示在以后的某个时间获取数据的能力,但数据本身仍然潜伏在组成linq查询的原始集合中。 (以及从表达式创建新值的任何逻辑)
这就是为什么在不使用ToXxx
方法的情况下存在各种警告以防止存储这些结果,如果您有可能实际上导致查询多次执行。
答案 1 :(得分:3)
它是否仍然属于源类型?它是否存储在伪数组中?它是上述的某种组合吗?
每次访问生成的IEnumerable<T>
时,大多数LINQ扩展方法都会遍历源代码(称为延迟执行)。结果通常不存储在中间源中。
是否有任何理由为什么转换为一种类型的IEnumerable总是比转换为另一种类型的
更快
是的,调用ToArray
或ToList
执行可枚举并实现它。如果您不使用返回的IEnumerable<T>
,则不会实现它。性能影响约为0。
答案 2 :(得分:0)
实际上是WhereEnumerableIterator
(如果myCol是IEnumerable
)。
http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,119
它仅包含对初始myCol
的引用和对Func<T, bool>
的引用。
如果mycol
是另一种类型,它可能是另一种更优化的LINQ迭代器。
答案 3 :(得分:0)
执行myCol.Where(myBoolMethod)
时,实际上没有枚举数据。它不存储在数组或其他任何内容中,您只需获取枚举器即可枚举此集合。
执行.ToArray()
时,它实际上使用枚举器来创建新数组。