2010-08-02 69 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

如果您還有其他類似的代碼段,您可以隨時在代碼中指定或放置一些計時器,然後運行基準類型測試以查看自己。另一個因素是內存佔用,其他人已經評論過。

相關問題