2013-04-15 43 views
-4

考慮下面的代碼。 's'被分成兩個不同的數組。爲什麼不分割優化?

string s = "1,2,3"; 
string[] arr = s.Split(','); 
string[] arr2 = s.Split(','); 

foreach (..) 
{ // do something 
} 

在發佈模式下編譯時,IL看起來像這樣,所以Split實際上被調用了兩次。有沒有一個原因,爲什麼沒有優化?

IL_0008: newarr [mscorlib]System.Char 
IL_000d: stloc.s CS$0$0000 
IL_000f: ldloc.s CS$0$0000 
IL_0011: ldc.i4.0 
IL_0012: ldc.i4.s 44 
IL_0014: stelem.i2 
IL_0015: ldloc.s CS$0$0000 
IL_0017: callvirt instance string[] [mscorlib]System.String::Split(char[]) 
IL_001c: stloc.1 
IL_001d: ldloc.0 
IL_001e: ldc.i4.1 
IL_001f: newarr [mscorlib]System.Char 
IL_0024: stloc.s CS$0$0001 
IL_0026: ldloc.s CS$0$0001 
IL_0028: ldc.i4.0 
IL_0029: ldc.i4.s 44 
IL_002b: stelem.i2 
IL_002c: ldloc.s CS$0$0001 
IL_002e: callvirt instance string[] [mscorlib]System.String::Split(char[]) 
+3

你爲什麼不自己優化代碼? – Raptor

+1

你爲兩個不同的數組調用'Split'兩次,所以編譯器調用'Split'兩次。我不明白你的問題。你在等什麼樣的優化? –

+1

親愛的,如果你爲同一個字符串調用兩次Split,那麼編譯器的錯誤是什麼。 –

回答

2

蒸餾評論到一個答案:

編譯器,在一般情況下,有一個方法的內容沒有專業知識 - 即使它could分析當前實現,它沒有辦法知道這個實施是否會在重要細節上發生變化。

您假設編譯器可以執行的優化的兩個最明顯的問題是確定性和副作用的存在。

  1. 確定性 - 有不保證對相同功能的兩個連續的調用將產生相同的結果,即使在不存在任何(明顯的)共享狀態。

  2. 副作用 - 有問題的功能(或稱它所調用的功能)可能產生明顯的副作用 - 即使增加一個呼叫計數器也是如此 - 這樣調用一次或兩次將會產生不同的總體效果。

現在的確,有時候,編譯器可以避開我們自己無法做到的技巧 - 例如,它可能可能知道,連續調用Split(),使用本地引用,不能被分配一個更可見的引用的副本,應該產生相同的結果。但這是難以置信的特定優化,可能不值得工程努力。

通用,編譯器沒有比方法簽名更多的知識。而且,在當前的.NET版本中,方法簽名不提供有關確定性和副作用的信息。