如果我有以下代码:
List<MyClass> list = GetList();
list.ForEach(i => i.SomeMethod());
让我们说SomeMethod()
抛出异常。 ForEach
继续迭代,还是只是停在那里?
如果它终止,有没有办法让集合中的其余项目运行他们的方法?
答案 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块总是好的。否则,你永远不会找到罪魁祸首。