Если вы хотите обработать исключение во время обработки результата перечисления, тогда вы пытаетесь, чтобы логика просто шла прямо в ваш цикл for / while.
Но ваш пример читается какесли вы пытаетесь перехватить и пропустить исключения, вызванные поставщиком перечисления.
Насколько я могу убедиться, в C # нет способа перебирать перечислитель и пропускать и исключение, которое происходит внутри самого перечислителя.,Если перечислитель вызывает исключение, то все последующие вызовы MoveNext () приведут к ложному выводу.
Самый простой способ объяснить, почему это происходит, с помощью этого простого перечислимого очень :
IEnumerable<int> TestCases()
{
yield return 1;
yield return 2;
throw new ApplicationException("fail eunmeration");
yield return 3;
yield return 4;
}
Понятно, что когда мы смотрим на этот пример, очевидно, что выброшенное исключение вызовет выход всего этого блока, а 3-й и 4-й оператор yield никогда не будут обработаны.Фактически, вы получите обычное предупреждение компилятора «Обнаружен недоступный код» в 3-м операторе yield.
Так что, когда перечисление является более сложным, применяются те же правила:
IEnumerable<int> TestCases2()
{
foreach (var item in Enumerable.Range(0,10))
{
switch(item)
{
case 2:
case 5:
throw new ApplicationException("This bit failed");
default:
yield return item;
break;
}
}
}
КогдаВозникает исключение, обработка этого блока прекращается и передается обратно в стек вызовов к ближайшему обработчику исключений.
ВСЕ работающие примеры, чтобы обойти эту проблему, которую я обнаружил на SO, не переходят кследующий элемент в перечислении, все они break при первом исключении.
Поэтому, чтобы пропустить en исключение в перечислении, вам понадобится поставщик, чтобы облегчить его.На самом деле это возможно только в том случае, если ваш код провайдера или вы можете связаться с разработчиком, который это сделал, приведенный ниже упрощенный пример того, как вы могли бы достичь этого:
IEnumerable<int> TestCases3(Action<int, Exception> exceptionHandler)
{
foreach (var item in Enumerable.Range(0, 10))
{
int value = default(int);
try
{
switch (item)
{
case 2:
case 5:
throw new ApplicationException("This bit failed");
default:
value = item;
break;
}
}
catch(Exception e)
{
if (exceptionHandler != null)
{
exceptionHandler(item, e);
continue;
}
else
throw;
}
yield return value;
}
}
...
foreach (var item in TestCases3(
(int item, Exception ex)
=>
Console.Out.WriteLine("Error on item: {0}, Exception: {1}", item, ex.Message)))
{
Console.Out.WriteLine(item);
}
Это даст следующий вывод:
0
1
Error on item: 2, Exception: This bit failed
3
4
Error on item: 5, Exception: This bit failed
6
7
8
9
Я надеюсь, что это прояснит проблему для других разработчиков в будущем, так как это довольно распространенная идея, которую мы все получим, как только начнем получатьглубоко в Linq и перечисления.Мощные вещи, но есть некоторые логические ограничения.