.Net - 什么时候 List.ForEach 优于标准 foreach 循环?
通用列表类具有 .ForEach(Action
方法。 现在我已经对它们的执行方式做了一些简单计时,看起来通用的 ForEach 的性能较差。 (代码段编译器友好)代码如下 -
public static class timer{
public static long foreachloop = 0;
public static long Gforeachloop = 0;}
public class something{
public List<string> myStrings = new List<string>();
public something()
{
for(int i = 1; i<=5000000;i++)
{
myStrings.Add(i.ToString());
}
}}
public class cls1{
private static List<string> Strings = new List<string>();
private static List<string> OtherStrings = new List<string>();
public static void RunSnippet()
{
something s = new something();
Stopwatch watch = new Stopwatch();
watch.Start();
foreach(string x in s.myStrings)
{
Strings.Add(x);
}
watch.Stop();
timer.foreachloop = watch.ElapsedMilliseconds;
watch.Reset();
watch.Start();
s.myStrings.ForEach(delegate(string n){OtherStrings.Add(n);});
s.myStrings.Clear();
watch.Stop();
timer.Gforeachloop = watch.ElapsedMilliseconds;
WL("FOREACH-"+timer.foreachloop + ",Count = " + Strings.Count);
WL("GFOREACH-"+timer.Gforeachloop + ",Count = " + OtherStrings.Count);
}
#region Helper methods
public static void Main()
{
try
{
RunSnippet();
}
catch (Exception e)
{
string error = string.Format("---\nThe following error occurred while executing the snippet:\n{0}\n---", e.ToString());
Console.WriteLine(error);
}
finally
{
Console.Write("Press any key to continue...");
Console.ReadKey();
}
}
private static void WL(object text, params object[] args)
{
Console.WriteLine(text.ToString(), args);
}
private static void RL()
{
Console.ReadLine();
}
private static void Break()
{
System.Diagnostics.Debugger.Break();
}
#endregion
}
FOREACH 的运行时间为 177 毫秒,GFOREACH 的运行时间为 707 毫秒。
现在我猜想使用它有一个很好的理由,但我就是想不出一个。 显然性能不是原因,所以问题是什么时候它是最佳选择?
提前致谢。
The generic list class has a .ForEach(Action<T> action)
method. Now i've done some simple timings of how they both perform and it seems that the generic ForEach is the poorer performer. The (Snippet Compiler Friendly) code is below -
public static class timer{
public static long foreachloop = 0;
public static long Gforeachloop = 0;}
public class something{
public List<string> myStrings = new List<string>();
public something()
{
for(int i = 1; i<=5000000;i++)
{
myStrings.Add(i.ToString());
}
}}
public class cls1{
private static List<string> Strings = new List<string>();
private static List<string> OtherStrings = new List<string>();
public static void RunSnippet()
{
something s = new something();
Stopwatch watch = new Stopwatch();
watch.Start();
foreach(string x in s.myStrings)
{
Strings.Add(x);
}
watch.Stop();
timer.foreachloop = watch.ElapsedMilliseconds;
watch.Reset();
watch.Start();
s.myStrings.ForEach(delegate(string n){OtherStrings.Add(n);});
s.myStrings.Clear();
watch.Stop();
timer.Gforeachloop = watch.ElapsedMilliseconds;
WL("FOREACH-"+timer.foreachloop + ",Count = " + Strings.Count);
WL("GFOREACH-"+timer.Gforeachloop + ",Count = " + OtherStrings.Count);
}
#region Helper methods
public static void Main()
{
try
{
RunSnippet();
}
catch (Exception e)
{
string error = string.Format("---\nThe following error occurred while executing the snippet:\n{0}\n---", e.ToString());
Console.WriteLine(error);
}
finally
{
Console.Write("Press any key to continue...");
Console.ReadKey();
}
}
private static void WL(object text, params object[] args)
{
Console.WriteLine(text.ToString(), args);
}
private static void RL()
{
Console.ReadLine();
}
private static void Break()
{
System.Diagnostics.Debugger.Break();
}
#endregion
}
FOREACH comes out at 177ms and GFOREACH at 707ms.
Now I'm guessing there's a good reason for using it but i just can't think of one. Clearly performance isn't the reason so the question is when would it be the best option?
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Eric Lippert 的这篇博客文章提供了背景信息:
http://blogs.msdn.com/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx
他正在谈论扩展方法的常见建议,以对
执行相同的操作IEnumerable
,但哲学上的反对也适用于List.ForEach
。这表明也许这种方法从来都不是一个好主意,尽管它看起来“很酷”。 使用
foreach
会更清楚。我建议可以将此类方法视为 修复了经典的循环变量闭包错误。
但在实践中,我越来越善于发现此类错误。
This blog post from Eric Lippert gives the background:
http://blogs.msdn.com/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx
He's talking about the common suggestion of an extension method to do the same thing for
IEnumerable<T>
, but the philosophical objection applies toList<T>.ForEach
as well.This suggests that maybe that method was never such a good idea, although it looks "cool". It's clearer to just use
foreach
.I've suggested that such methods can be thought of as a fix for the classic closure-over-loop-variable bug.
But in practice I've just got better at spotting such bugs.
当它看起来更整洁时。
根本不是开玩笑。 真的,我是说真的。 根据您的情况选择更具可读性的样式。 例如,如果您只想对每个项目调用一个方法,例如:
这种风格更适合。 但是,如果您有一百行作为循环体,或者您有嵌套循环和控制流结构,则旧样式看起来更好。
When it looks neater.
Not a joke at all. Really, I mean it. Go with the more readable style in your case. For instance, if you just want to call a method on each item like:
this style suits better. However, if you are having a hundred lines as the body of the loop, or you have nested loops and control flow constructs, the old style looks better.