当前位置: 首页 > 编程语言 > C#

何时在本机foreach循环中使用List.ForEach?

时间:2023-04-11 00:35:58 C#

我什么时候可以在原生foreach循环中使用List.ForEach?这两种方法都有优势吗?如果我需要遍历List项,对每一项进行操作,是使用传统的foreach循环机制还是继续使用List.ForEach?MatthewPodwysocki@CodeBetter.com写了一篇关于反竞选的有趣文章。这让我想到了循环试图解决的问题。在这篇文章中,Matthew认为显式循环结构会让您思考“如何”而不是“什么”。是否有充分的理由使用一个而不是另一个(如果有的话)?首先,如果您出于任何原因通过代表申请,您将使用它。例如,您可以创建自己的列表、填充它等,然后将委托应用于每个条目。那时,写作:list.ForEach(action);比foreach(Itemiteminlist){action(item);更简单我发现List.ForEach要快得多。以下是(现已修订)性能测试的最后四次运行的结果:NativeForLoop:00:00:04.7000000ListDotForEach:00:00:02.7160000-------------------------------------NativeForLoop:00:00:04.8660000ListDotForEach:00:00:02.6560000-----------------------------------NativeForLoop:00:00:04.6240000ListDotForEach:00:00:02.8160000-----------------------------------NativeForLoop:00:00:04.7110000ListDotForEach:00:00:02.7190000每个测试执行1亿次(100,000,000)迭代。我更新了测试以使用自定义类(Fruit)并让每个循环遍历并使用当前对象中的成员。每个循环执行相同的任务。这是测试类的完整源代码:classForEachVsClass{staticInt32Iterations=1000000000;静态int工作=0;publicstaticvoidInit(string[]args){if(args.Length>0)Iterations=Int32.Parse(args[0]);Console.WriteLine("迭代次数:"+Iterations);}staticListListOfFruit=newList{newFruit("Apple",1),newFruit("Orange",2),newFruit("Kiwi",3),newFruit("Banana",4)};内部类水果{公共字符串名称{得到;放;}publicint值{得到;放;}publicFruit(string_Name,int_Value){Name=_Name;值=_值;}}[基准测试]publicstaticvoidNativeForLoop(){for(intx=0;xWork+=f.Value);这是工作方法的结果IL(提取出来以便于阅读):.methodpublichidebysigstaticvoidNativeForLoopWork()cilmanaged{.maxstack2.localsinit([0]classForEachVsClass/FruitCurrentFruit,[1]valuetype[mscorlib]System.Collections.Generic.List`1/EnumeratorCS$5$0000)L_0000:ldsfld类[mscorlib]System.Collections.Generic.List`1ForEachVsClass::ListOfFruitL_0005:callvirt实例valuetype[mscorlib]System.Collections.Generic.List`1/Enumerator[mscorlib]System.Collections.Generic.List`1::GetEnumerator()L_000a:stloc.1L_000b:br.sL_0026L_000d:ldloca.sCS$5$0000L_000f:调用实例!0[mscorlib]System.Collections.Generic.List`1/Enumerator::get_Current()L_0014:stloc.0L_0015:ldsfldint32ForEachVsClass::WorkL_001a:ldloc.0L_001b:callvirt实例int32ForEachVsClass/Fruit::get_Value()L_0020:添加L_0021:stsfldint32ForEachVsClass::WorkL_0026:ldloca.sCS$5$0000L_0028:调用实例bool[mscorlib]System.Collections.Generic.List`1/Enumerator::MoveNext()L_002d:brtrue.sL_000dL_002f:leave.sL_003fL_0031:ldloca.sCS$5$0000L_0033:约束[mscorlib]System.Collections.Generic.List`1/枚举器L_0039:callvirt实例无效[??mscorlib]System.IDisposable::Dispose()L_003e:endfinallyL_003f:ret.tryL_000btoL_0031finallyhandlerL_0031toL_003f}.methodpublichidebysigstaticvoidListDotForEachWork()cilmanaged{.maxstack8L_0000:ldsfld类[mscorlib]System.Collections.Generic.List`1ForEachVsClass::ListOfFruitL_0005:ldsfld类[mscorlib]System.Action`1ForEachVsClass::CS$9__CachedAnonymous1MethodDelegateL_000a:brtrue.sL_001dL_000c:ldnullL_000d:ldftnvoidForEachVsClass::b__0(classForEachVsClass/Fruit)L_0013:newobj实例void[mscorlib]System.Action`1::.ctor(object,nativeint)L_0018:stsfld类[mscorlib]System.Action`1ForEachVsClass::CS$9__CachedAnonymousMethodDelegate1L_001d:ldsfld类[mscorlib]System.Action`1ForEachVsClass::CS$9__CachedAnonymousMethodDelegate1L_0022:callvirt实例无效[??mscorlib]System.Collections.Generic.List`1::ForEach(class[mscorlib]System.Action`1)L_0027:ret}如果您希望将现有委托传递给.ForEach()我只看到一个优势在大多数其他情况下,我认为使用trueforeach()更有效和可读.EricLippert反对IEnumerable.ForEach(),我可以看到争论的双方。抛开它的论点并实施它,我发现它的简洁性和可读性让我感到一些小小的乐趣,制作了几个代码块。因为我通常不需要考虑使用LINQ的副作用,所以我也可以理解他为什么不附带它。对于ForEach(),代表的情况有点强烈,但我不认为标准的foreach循环掩盖了意图。我认为没有明确的正确或错误答案。我同意MatthewPodwysocki的观点。除非您要传递委托并希望使用其中之一循环遍历集合,否则我会坚持使用标准循环构造。有时我发现在.ForEach()内的Lambda表达式中,我可以更轻松地阅读代码。它还使您不必显式编写要迭代的类型。因为它是强类型的,所以编译器已经知道了。示例:logs.ForEach(log=>{log.DoSomething();});List.ForEach的问题是无法在内部传递属性ref或out。在大多数其他情况下,我认为使用List.ForEach更具可读性。以上是C#学习教程:原生foreach循环什么时候用List.ForEach?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: