2011-09-12 35 views
0

我有以下代碼,我試圖將ICollectionView返回的每個元素都轉換爲不同的對象。如何在foreach循環中處理InvalidOperationException包含yield返回?

public IEnumerator GetEnumerator() 
    { 
     foreach (TOriginal original in _collectionView) 
     { 
      if (!Equals(original, null)) 
      { 
       yield return GetTranslated(original); 
      } 
      else 
      { 
       yield return default(TTranslated); 
      } 
     } 
    } 

如果_collectionView是在foreach期間改變(這是在我的測試應用中發生的),那麼這將引發InvalidOperationException,而是因爲VisualStudio的抱怨「「產量回報,我不能在包裝一個try/catch foreach循環'語句不能出現在try/catch塊中「。

我該如何處理異常?

+0

你真的需要處理異常嗎?我會想象,*不處理它,讓它冒泡給調用者將是最明顯的行爲。 – LukeH

+0

@LukeH這是一個好點,也許我看着錯誤的問題 – Grokodile

回答

3

如果集合被修改,枚舉器不需要保持有效。標準的行爲是,如果集合在枚舉中被修改,枚舉器將在下次調用MoveNext時拋出InvalidOperationException。

我相信讓InvalidOperationException傳播是正確的行爲。您的枚舉器將具有與所有標準集合類相同的語義,因此您的類的消費者會期待這一點。

如果您的類的消費者需要在迭代過程中更改列表,它們應該使用索引值進行循環,並在修改列表時根據需要更改索引器。

1

yield return不能在try...catch中,但這並不意味着在獲取要返回的值時無法捕獲異常。

例子:

object value; 
try { 
    value = SomeCodeThatCanBreak(); 
} catch (SomeException ex) { 
    // you could silently skip this item: 
    value = null; 
} 
if (value != null) { 
    yield return value; 
} 

如果異常指示集合已經改變,你會退出但圈外的,而不是跳躍的項目,因爲你不會得到任何更多的項目進行枚舉的。

您必須決定哪種操作適合您捕獲的每種異常類型。在某些情況下,默默處理異常可能是合乎邏輯的,但在大多數情況下,您應該讓異常冒出來,或者拋出一個不同的異常(如果更好地描述了該問題)。