C#如何在不中断循环的情况下抛出异常

7
void function() {
    try
    {
        // do something

        foreach (item in itemList)
        {
            try 
            {
                //do something
            }
            catch (Exception ex)
            {
                throw new Exception("functionB: " + ex.Message);
            }
        }
    }
    catch (Exception ex)
    {
        LogTransaction(ex.Message);
    }
}

您好,我希望可以从for循环中将异常抛出到其父级。目前,当for循环中出现异常时,该循环将被终止。 是否有任何方法修改它,使异常被抛出但循环仍然继续?


我认为你可能想看一下异步事件。http://msdn.microsoft.com/en-us/library/ms228974.aspx和http://msdn.microsoft.com/en-us/library/e7a34yad.aspx - Adriaan Stander
2
你能澄清一下期望的行为吗?我不明白想要抛出异常并继续循环是什么意思。你想要将所有异常推迟到循环完成之后再处理吗?还是让父级从下一个项目继续迭代?还是其他什么? - Alexei Levenkov
4个回答

22

不,你不能从循环中抛出异常并继续迭代。但是你可以将异常保存在数组中,在循环后进行处理。像这样:

List<Exception> loopExceptions = new List<Exception>();
foreach (var item in itemList)
  try 
  {
    //do something
  }
  catch (Exception ex)
  {
    loopExceptions.Add(ex);
  }

foreach (var ex in loopExceptions)
  //handle them

6
使用AggregateException一次性将它们全部抛出可能是处理它们的好方法。 - Thorarin
可能吧,但这只是一个选择的问题 - 他仍然需要遍历所有内部异常。 - JleruOHeP

1
在您的循环内部构建一个try-catch块,并且不要再次抛出异常。

我需要外部的try-catch块,因为在外部部分可能会发生异常,并且需要抛出异常,因为我需要记录该过程。 - noobie

0

这个怎么样?

void function() {
    var IsCompleted = false;
    try
    {
        // do something

        foreach (item in itemList)
        {
            try 
            {
                //do something
            }
            catch (Exception ex)
            {
                throw new Exception("functionB: " + ex.Message);
            }
            var IsCompleted = true;
        }
    }
    catch (Exception ex)
    {
        LogTransaction(ex.Message);
    }

    If (!IsCompleted)
       function();
}

1
这也是一种选择,但在这种情况下,for循环将不得不从头开始重新开始,无论如何谢谢。 - noobie

0

throw 语法被设计成隐式中断执行,并将其“冒泡”到最接近具有 catch 语法的调用者。

一旦捕获异常,就没有办法恢复循环的执行,就像在(例如)Classic ASP或VB Script中一样。

关键是异常应该是罕见的。 它们不应该被用作控制应用程序流程的方法。

如果您的意图是要允许其他内容处理错误,您应该改为构建代码,使您可以传递错误处理程序。

其中一个示例是:

void Process(IEnumerable<object> data, Action<object, Exception> handleError) 
{

    foreach(var o in data) 
    { 
        try 
        { 
            // do something
        }
        catch(Exception ex)
        {
            handleError(o, ex); 
        }
    }
}

这样调用:

Process(data, (obj, ex) => RequeueForProcessingDueToError(obj.Id, ex.Message)); 

这允许您传递一个处理错误功能的委托。您可以通过多种方式传递委托:例如事件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接