2013-03-18 102 views
0

我很好奇在明年情況下,編譯效率:C#空合併運算符(?)編譯器代碼優化

double total = list.Sum(x => x.Value) ?? 0; 

問:編譯器會產生代碼,將一次或兩次執行Sum函數?

它可以產生類似:

double total = list.Sum(x => x.Value) == null ? 0 : (double)list.Sum(x => x.Value); 

double temp = list.Sum(x => x.Value); 
total = temp == null ? 0 : (double)temp; 

回答

8

您的代碼是沒有意義的,因爲即使彙總所有空值將導致0

var d = new int?[]{null,null}; 
d.Sum().Dump(); //0 

...所以Enumerable.Sum()決不屈服你要警惕null值。

+1

+1 - '如果源不包含任何元素,則此方法返回零。「並且 '結果不包含null值':from:http://msdn.microsoft.com/en-us/library/bb383052.aspx – Habib 2013-03-18 11:36:35

+0

@Habib我讀過的msdn文檔對我來說有點不清楚。如果源只包含null,會發生什麼?是由源代碼隱含的元素沒有空元素?他們可以輕易地說:返回結果永遠不會爲空,這將更清晰。方法返回int的事實? (IEnumerable )導致我錯誤地認爲它可以返回null類型。 – Goran 2013-03-18 12:12:43

+1

@Goran:同意。保持返回類型爲空可能是愚蠢的。 – spender 2013-03-18 12:14:35

4

的代碼將執行Sum一次。這就是在語言中引入新操作員的關鍵。可以通過引入與條件的副作用,並驗證該副作用被施加一次驗證:

int? x = 5; 
int y = x++ ?? 100; 

執行該代碼後,x6,不7

+0

[鏈接到ideone](http://ideone.com/PIxPbo)。 – dasblinkenlight 2013-03-18 11:40:44

0

??運算符只適用於可爲空的類型,並且double不是可以爲空的類型,所以此代碼不會編譯。 同樣,.Sum()擴展方法將永遠不會在此列表上返回null,它將始終返回0

+0

我看不出有什麼原因導致代碼無法編譯...... – Goran 2013-03-18 12:20:54

+0

在你的情況下,代碼有兩個問題:(1)你試圖爲一個double類型的int型值共同賦值變量(如果你需要一個雙引號,你應該使用'0.0'或'0d')和(2)如果你的參數是不可空的,那麼你不能使用'??'運算符(並且'double'是不可空的,與'double?'相比)。 – 2013-03-18 12:48:18

+0

如果列表包含可爲空的元素,則參數爲空,所以它會編譯得很好。 – Goran 2013-03-18 13:00:08