如果在List <t> .ForEach中抛出异常,迭代是否会停止?</t>

时间:2012-05-17 06:00:43

标签: c# exception foreach

如果我有以下代码:

List<MyClass> list = GetList();
list.ForEach(i => i.SomeMethod());

让我们说SomeMethod()抛出异常。 ForEach继续迭代,还是只是停在那里?

如果它终止,有没有办法让集合中的其余项目运行他们的方法?

3 个答案:

答案 0 :(得分:13)

是的,如果抛出异常,循环退出。如果您不想要这种行为,则应将异常处理放入您的委托中。您可以轻松地为此创建包装器方法:

public static Action<T> SuppressExceptions<T>(Action<T> action)
{
    return item =>
    {
        try
        {
            action(item);
        }
        catch (Exception e)
        {
            // Log it, presumably
        }
    };
}

说实话,如果可能,我会尝试以避免这种情况。抓住所有这样的异常是令人不愉快的。它也不会记录失败的项目或异常等。您需要更详细地考虑您的要求:

  • 您是否需要收集失败的物品?
  • 您是否需要收集例外情况?
  • 您想要捕捉哪些例外?

创建一个使用普通foreach循环的单独方法,处理错误并收集错误几乎肯定会更清晰。就个人而言,我通常更喜欢使用foreach而不是ForEach - 您可能希望阅读Eric Lippert's thoughts on this too

答案 1 :(得分:3)

会抛出错误。您也正在重新实现foreach。怎么样:

foreach (var item in list)
{
    try
    {
        // dangerous thing with item
    }
    catch (Exception e)
    {
        // how do you want to log this?
    }
}

这有利于在大多数.NET版本中工作,并且明显具有副作用。当然,您可以将此代码直接放在ForEach委托中,但我只建议如果它本身就是一个方法(而不是lambda函数)。


合理的替代方法是创建自己的ForEachWithCatch扩展程序,捕获所有异常并将其发送回调用方:

public static IEnumerable<Tuple<T,Exception>> ForEachWithCatch<T>(this IEnumerable<T> items, Action<T> action)
{
    var exceptions = new List<Tuple<T,Exception>>();

    foreach(var item in items)
    {
        try
        {
            action(item);
        }
        catch(Exception e)
        {
            exceptions.Add(Tuple.Create(item, e));
        }
    }

    return exceptions;
}

这会发回每个失败的项目的可枚举,并且它是相应的异常。

答案 2 :(得分:0)

如果您的SomeMethod已实施try-catch块,则foreach将继续

void SomeMethod()
{
  try
  {
    //Some operation on i 
  }
  catch(Exception ex)
  {
  }
}

但如果没有,那么foreach就会破裂。

这样做就是这样

list.ForEach(i => 
     {
         try
         {
             i.SomeMethod();
         }
         catch(Exception ex)
         {
         }
     });

但是在代码中使用零try-catch块总是好的。否则,你永远不会找到罪魁祸首。