LINQ IEnumerable <t>内存结构

时间:2017-04-26 08:58:24

标签: c# linq memory

因此,我了解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()更快无论涉及哪种数据类型?

4 个答案:

答案 0 :(得分:5)

它不是存储。它表示在以后的某个时间获取数据的能力,但数据本身仍然潜伏在组成linq查询的原始集合中。 (以及从表达式创建新值的任何逻辑)

这就是为什么在不使用ToXxx方法的情况下存在各种警告以防止存储这些结果,如果您有可能实际上导致查询多次执行。

答案 1 :(得分:3)

  

它是否仍然属于源类型?它是否存储在伪数组中?它是上述的某种组合吗?

每次访问生成的IEnumerable<T>时,大多数LINQ扩展方法都会遍历源代码(称为延迟执行)。结果通常不存储在中间源中。

  

是否有任何理由为什么转换为一种类型的IEnumerable总是比转换为另一种类型的

更快

是的,调用ToArrayToList 执行可枚举并实现它。如果您不使用返回的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()时,它实际上使用枚举器来创建新数组。