2016-02-08 51 views
0
foreach (var item in Model.PublishedSong.RelatedSongs.Select((value, i) => new { value, i }) ?? Enumerable.Empty <dynamic>()) 
{ 

} 

相關歌曲可能是也可能不是null,有沒有什麼方法可以在這裏使用null合併運算符?我仍然得到錯誤信息:在選擇表達式的foreach中使用空合併運算符

值不能爲空

+1

爲什麼在迭代它們之前不測試用於null的RelatedSongs?這種複雜的代碼與什麼點?運營商? – Dennis

+1

你期待什麼'null',Model.PublishedSong.RelatedSong'的某個部分,還是該集合中的某些項目?基本上'Select'不會返回'null',所以編譯器告訴你,現在你的空合併運算符永遠不會被使用。 – juharr

回答

4

如果RelatedSongs爲空,調用它Select將拋出一個NullReferenceException,因爲只有後,左側是解決空合併運算符進行評估。而且由於解決左手邊的問題會導致一個例外,所以對你沒有任何好處。

如果您正在使用C#6.0中,可以使用空傳播運營商 - ?. - 調用僅當RelatedSongs不爲空,並使用空合併運算符,否則:

// This will return null if Relatedsongs is null, or call Select otherwise. 
foreach (var item in Model.PublishedSong.RelatedSongs?.Select((value, i) => new { value, i }) 
          ?? Enumerable.Empty <dynamic>()) 
{ 
} 

如果您「再使用C#5或更早版本,您必須手動檢查空:

foreach (var item in Model.PublishedSong.RelatedSongs != null 
          ? Model.PublishedSong.RelatedSongs.Select((value, i) => new { value, i }) 
          : Enumerable.Empty <dynamic>()) 
{ 
} 
+3

就我個人而言,我認爲它會更易於檢查集合是否爲「null」,如果是,則跳過「foreach」。 – juharr

+0

@juharr我同意,但傾向於保留文體選擇,並專注於問題本身。 –

1

喜歡這個?

[編輯:刪除的簡化]

Model.PublishedSong 
    .SelectMany(x=> 
     (x.RelatedSongs??Enumerable.Empty<Song>()) 
     .Select((x,i) => new {Value = x, Index = i)); 

它評估到單個可枚舉,而不是兩個。

+0

這與OP不同。你正在使用?以交替選擇值,而OP使用它來選擇兩個序列。 – Dennis

+0

他在錯誤的地方使用它,在他的例子中,它的左邊不會爲空。 –

0

我覺得@ juharr的評論是好的 - 如果執行循環之前的空支票可能更具可讀性。但是,如果你真的想使用空合併運算符,這將這樣的伎倆:

foreach (var item in (Model.PublishedSong.RelatedSongs ?? Enumerable.Empty<TypeOfRelatedSong>()).Select((value, i) => new { value, i })) 
{ 

} 

你必須嘗試遍歷RelatedSongs之前執行空校驗。在你的問題的例子中,你正在嘗試迭代之後做它,因此是例外。