Как обработать InvalidOperationException в цикле foreach, содержащем доходность? - PullRequest
0 голосов
/ 12 сентября 2011

У меня есть следующий код, в котором я пытаюсь взять каждый элемент, возвращенный ICollectionView, и перевести его в другой объект.

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

Если _collectionView изменяется во время foreach (это происходит в моем тестовом приложении), оно генерирует исключение InvalidOperationException, но я не могу обернуть цикл foreach в try / catch, потому что VisualStudio жалуется на «оператор yield return». появляется в блоке try / catch ".

Как я могу обработать исключение?

Ответы [ 2 ]

3 голосов
/ 12 сентября 2011

Перечислители не обязаны оставаться действительными, если коллекция изменена. Стандартное поведение состоит в том, что если коллекция изменяется в середине перечисления, перечислитель сгенерирует исключение InvalidOperationException при следующем вызове MoveNext.

Я полагаю, что распространение InvalidOperationException - это правильное поведение. Ваш перечислитель будет иметь ту же семантику, что и все стандартные классы коллекций, так что потребители вашего класса ожидают этого.

Если потребителям вашего класса необходимо изменить список во время итерации, они должны выполнить цикл с использованием значения индекса и при необходимости изменять индексатор при изменении списка.

1 голос
/ 12 сентября 2011

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;
}

Если исключение указывает на то, что коллекция изменилась, вы, тем не менее, выйдете из цикла, а не пропустив элементы, поскольку вы не получите больше элементов из перечислителя.

Вы должны решить, какое действие должно подходить для каждого типа исключений, которые вы ловите. В некоторых ситуациях может быть логично тихо обрабатывать исключения, но в большинстве ситуаций вы должны позволить всплыть исключению или вызвать другое исключение, если это лучше описывает проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...