我有以下代码,我试图将ICollectionView返回的每个元素转换为另一个对象。
public IEnumerator GetEnumerator()
{
foreach (TOriginal original in _collectionView)
{
if (!Equals(original, null))
{
yield return GetTranslated(original);
}
else
{
yield return default(TTranslated);
}
}
}
如果在foreach期间更改了_collectionView(这在我的测试应用程序中发生),那么它会抛出InvalidOperationException,但是我无法在try / catch中包装foreach循环,因为VisualStudio会抱怨“'yield return'语句无法' t出现在try / catch块中。“
我该如何处理异常?
答案 0 :(得分:3)
如果修改了集合,则不需要枚举器保持有效。标准行为是,如果在枚举过程中修改了集合,则枚举器将在下次调用MoveNext
时抛出InvalidOperationException。
我相信让InvalidOperationException传播是正确的行为。您的枚举器将具有与所有标准集合类相同的语义,因此您的类的消费者将期望这样。
如果您的类的使用者需要在迭代期间更改列表,则应使用索引值循环,并在修改列表时根据需要更改索引器。
答案 1 :(得分: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;
}
如果异常表明集合已经更改,那么您将退出循环而不是跳过项目,因为您将不再从枚举器中获取任何项目。
您必须决定哪种操作适合您捕获的每种异常类型。在某些情况下,静默处理异常可能是合乎逻辑的,但在大多数情况下,您应该让异常冒泡,或者如果更好地描述问题则抛出异常。