2010-08-02 73 views
11

是这样的:会在循环内部/外部声明变量会改变性能吗?

foreach(Type item in myCollection) 
{ 
    StringBuilder sb = new StringBuilder(); 
} 

比慢得多:

StringBuilder sb = new StringBuilder(); 

foreach(Type item in myCollection) 
{ 
    sb = new StringBuilder(); 
} 

换句话说,它真身在何处,我宣布我的StringBuilder

+3

类似于http://stackoverflow.com/questions/2447475/best-practice-for-creating-objects-used-in-for-foreach-loops – 2010-08-02 14:14:38

+1

一个无关的错误是第二个版本应该初始化为null避免超额分配。 – 2010-08-02 14:32:02

回答

12

也许你可以得到一些性能,如果你这样写:

StringBuilder sb = new StringBuilder(); 
foreach(Type item in myCollection) 
{ 
    sb.Length = 0; 
} 

所以,你必须实例化StringBuilder的只有一次和复位的循环的大小,这应该是比实例化一个新的对象稍快。

+0

+1好点... – SLaks 2010-08-02 14:17:00

+1

+1:根据构建字符串的大小和sb中产生的内部缓冲区,这可能会产生可测量的差异。 – Alex 2010-08-02 14:34:49

+2

它可能,但它也可能不。当你调用'ToString'时,它复制缓冲区。我会以此为基准,假设有任何理由认为它对性能敏感。 – 2010-08-02 15:13:04

14

不,在您声明它的情况下,在性能方面无关紧要。

对于一般的代码清洁,你应该在它使用的最内层的范围声明 - 即。你的第一个例子。

+1

无论如何,这应该编译成相同的IL。那么,如果他不是初始化两次。 – 2010-08-02 14:14:02

+1

纠正我,如果我错了,但如果你在循环内声明它不会使它不可用(未声明)? – NullUserException 2010-08-02 14:19:28

+3

@NullUserException是的,你是对的。但是如果你不需要它在循环外部,在循环中声明它更清晰 – sloth 2010-08-02 14:21:50

2

在第二个例子中,您将创建一个额外的StringBuilder实例。除了它们都是相同的,所以性能问题是可以忽略的。

+0

这应该是我认为对这个问题的评论。 – Shaihi 2010-08-02 14:14:33

+0

@Shaihi - 为什么? w69rdy正在回答这个问题。 – mphair 2010-08-02 16:22:27

1

这里没有足够的代码来清楚地表明您的特定情况下的性能差异。话虽如此,但在大多数情况下,像这样在外部声明参考变量与外部声明之间的区别是微不足道的。

1

您的两个代码示例之间的有效差异是第二个将比第一个分配多一个StringBuilder实例。与其他应用程序相比,这对性能的影响基本上没有任何影响。

0

最好的检查方法是在循环中尝试两种方法,每种方法大约100.000。测量每次100.000次迭代所需的时间并进行比较。我不认为有很多不同。尽管如此,还是有一点小小的差别。第一个例子将具有与迭代次数一样多的变量。第二个例子只有一个变量。编译器足够聪明,可以在这里做一些优化,所以你不会注意到速度的提高。 但是,如果您不想在循环之外使用循环内生成的最后一个对象,那么第一个解决方案会更好。在第二种解决方案中,垃圾收集器释放最后创建的对象只需要一段时间。在第一个例子中,垃圾收集器在释放对象时会快一点。它依赖于代码的其余部分,但是如果在这个StringBuilder对象中存储了大量数据,那么第二个示例可能会持续更长的时间,因此在离开循环后,代码的性能会下降
然后,如果对象耗尽了100 KB,并且您的计算机上有16 GB的空间,那么没有人在意......垃圾收集器最终会再次释放它,可能会在您离开包含此循环的方法时立即释放它。

0

如果您还有其他类似的代码段,您可以随时在代码中指定或放置一些计时器,然后运行基准类型测试以查看自己。另一个因素是内存占用,其他人已经评论过。

相关问题