C# 枚举集合的不同方法

C# 枚举集合的不同方法,c#,collections,c#-4.0,C#,Collections,C# 4.0,从下面两种枚举集合的方法中,一种方法比另一种更可取,还是在性能方面两者都相同(即,由于第二种方法涉及ToList()转换) 或 if(MyTypes.OfType.Any()) 返回; 存在并行。ForEach: 显然,不转换集合要比转换集合快。当然,对于可索引集合,您可以使用经典for循环: for( int i = 0; i < collection.Count; i++ ) { collection[i] ... // do something with the item }

从下面两种枚举集合的方法中,一种方法比另一种更可取,还是在性能方面两者都相同(即,由于第二种方法涉及ToList()转换)

if(MyTypes.OfType.Any())
返回;

存在并行。ForEach:


显然,不转换集合要比转换集合快。

当然,对于可索引集合,您可以使用经典for循环:

for( int i = 0; i < collection.Count; i++ )
{
    collection[i] ... // do something with the item
}
枚举集合的所有不同方法在某些特定情况下都很有用,但在何处使用哪种模式是非常有关联的

例如,直接使用
IEnumerator
对象在需要细粒度控制迭代器的增量和访问方式以及时间时非常有用。许多LINQ操作符在内部使用
IEnumerator
来优化其实现


一个合理的经验法则是:当您访问项目以产生副作用时,应使用
for
foreach
,当您将一个序列转换(投影)到另一个序列时,应使用LINQ(选择、位置等)。使用LINQ强调结果,同时隐藏机制,而循环强调机制。

我更喜欢第一种方法,因为不会像转换为列表那样丢失底层枚举数。对于大多数集合来说,差别不大,但是如果是一个大集合,或者是一个通过产生结果来计算的集合,那么它可能很重要。

在您提到的那些集合中,首选第一个。第二种方法将做更多的工作,包括转换为列表和检查类型,最终只需执行foreach

当然还有其他的迭代方法,但它们取决于集合。对于
IList
实现和数组,您可以使用正常的
For
循环,并使用
myitem[i]
索引项

但没有理由不使用foreach,因为它适用于所有集合,而且在性能方面始终是最佳选择。我所说的优化是指算法复杂度/big-o

根据您的问题进行编辑编辑
通常,您应该使用提供最佳可读性(不会明显严重影响性能)的枚举方案。在您的示例中,如果您想查看列表中是否有任何特定类型的元素,那么我将使用LINQ路由(
collection.OfType…
)。它清楚地表达了意图,而且几乎可以阅读英文文本并理解其含义:“在我的集合中,获取类型为X的元素并告诉我是否有。”

对于某些类型的集合(如列表(T)),通过classic
foreach进行枚举要快得多。这是因为C#中的
foreach
construct不直接使用IEnumerator和IEnumerable


它调用GetEnumerator()方法,然后对返回的对象调用MoveNext()和Current。因为List返回ListNumerator结构,所以当直接调用或通过IEnumerator接口调用时,哪些方法更快。

应该使用哪种方法实际上取决于您尝试执行的操作。取决于集合(以及它是否扩展了CollectionBase),您只需引用IList接口和ForEach方法并对其进行迭代即可(无需先转换为列表)。@Brad Christie IList不支持ForEach,list支持。在集合的类型上。例如,OfType()根据类型筛选集合。如果您已经知道集合中的所有对象都是SomeType类型,那么就没有理由调用OfType()。另外,如果集合实现了ICollection,那么在ToList()中调用的列表构造函数的行为将比其他方法更有效。@chibacity,你说得对。我以为我在IList文档里。list类是实现ForEach的类。Touché,我站直了。+1。另请参见,您不需要说“For IList实现和数组”,因为数组实现IList。显然,在某些情况下,
for
foreach
稍微快一点,但还不足以产生影响。@phoog如果我的记忆还不错,数组以一种非常不寻常的方式支持IList,根据经验,将数组视为IList要慢几个数量级。也许他们已经解决了这个问题…@phoog:我怀疑这一点,但不确定,所以我把“…和数组”放在里面,以明确表示。谢谢你clairifying@chibacity:我不知道与IList的阵列实现存在显著的性能差异;谢谢你的警告。此外,我还想将此链接添加到我先前关于for vs foreach性能的评论中:N.B.无法将类型“System.Collections.IEnumerator”隐式转换为“System.IDisposable”。@grokofile:您是对的
IEnumerable
不扩展
IDisposable
,但是
IEnumerable
扩展了。
class SomeType : IMyType
{
}

class OtherType : IMyType
{
}

class SomeCollection<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable
{
}
foreach(IMyType mt in MyTypes) 
{   
  if(IMyType is SomeType)
  return; 
}
if(MyTypes.OfType<SomeType>.Any())
    return;
for( int i = 0; i < collection.Count; i++ )
{
    collection[i] ... // do something with the item
}
using( IEnumerator<YourType> e = collection.GetEnumerator() )
{
    while( e.MoveNext() )
    {
        // do something with the item
        e.Current ...
    }
}