何时使用LINQ的.ToList()或.ToArray()

运行此代码后:

var input = new List( ... ); var result = input.Select( t => new U(t) ); U first1 = null; foreach ( U u1 in result ) if ( first1 == null ) first1 = u1; U first2 = null; foreach ( U u2 in result ) if ( first2 == null ) first2 = u2; 

然后’first1 == first2’计算为false,即使两个U都包含相同的T.我还没有测试它,但我认为可以通过链接.ToList()或.ToArray()来评估为true进入Select()调用。

在比这个简单的插图复杂得多的实际代码中,用于决定是否应该附加.ToList()或.ToArray()的正确经验法则是什么? 我最初的想法是可以多次迭代的任何引用表达式,或者在潜在迭代不明显的情况下更安全,任何引用的表达式,其结果永远不会改变。

不幸的是,我不认为这里有一个很好的“硬性和快速”规则。 这很大程度上取决于您对结果的使用方式以及查询本身实际执行的操作。

我最初的想法是要么可以多次迭代的任何表达式,要么在潜在的迭代不明显的情况下更安全,任何结果永远不会改变的表达式。

通常,如果您要多次使用查询结果,通过ToList()ToArray()存储它总是一个好主意。 如果您的LINQ查询是“昂贵的”,则尤其如此,因为它可以防止昂贵的操作多次运行。

通常情况下,如果您只是枚举结果,那么我会将其保留为IEnumerable 。 如果您计划存储结果,或多次使用结果,那么将其存储在集合中可能是有益的。

另一个需要注意的地方是,如果您在公共API中返回结果。 虽然返回IEnumerable通常很好,但根据预期的用例,您可能需要考虑使用ToList()来防止操作被多次执行。

至于是否使用ToList()ToArray() ,它实际上取决于你将如何使用结果。 与每个相关的成本几乎相同(如果输入不是ICollectionToList()实际上具有略低的执行开销。 通常,我更喜欢ToList()不是ToArray()除非我对数组有特定需求或期望。

ToList调用List(IEnumerable)构造函数来创建List ,而ToArrary使用内部类Buffer来增长数组。

如果源集合( IEnumerable )实现ICollection接口,则这两种方法使用类似的代码逻辑来复制数据。

 ICollection.CopyTo(array, 0); 

否则, ToList将动态创建ListToArray将元素逐个复制到新数组中。 如果数组已满,则该方法将数组大小加倍以保存数据。 最后,该方法根据源集合的大小返回另一个数组。