我有一堆可以Process()
对象的类,并返回它们自己的对象:
public override IEnumerable<T> Process(IEnumerable<T> incoming) { ... }
我想编写一个可以包装这些处理器之一的处理器类,并记录包装的Process()
方法可能引发的任何未捕获的异常。我的第一个想法是这样的:
public override IEnumerable<T> Process(IEnumerable<T> incoming) {
try {
foreach (var x in this.processor.Process(incoming)) {
yield return x;
}
} catch (Exception e) {
WriteToLog(e);
throw;
}
}
但是由于CS1626: Cannot yield a value in the body of a try block with a catch clause,所以不起作用。
所以我想写一些概念上相同但可以编译的东西。 :-)我知道了:
public override IEnumerable<T> Process(IEnumerable<T> incoming) {
IEnumerator<T> walker;
try {
walker = this.processor.Process(incoming).GetEnumerator();
} catch (Exception e) {
WriteToLog(e);
throw;
}
while (true) {
T value;
try {
if (!walker.MoveNext()) {
break;
}
value = walker.Current;
} catch (Exception e) {
WriteToLog(e);
throw;
}
yield return value;
}
}
但是那比我希望的要复杂,而且我不能完全确定它的正确性还是没有更简单的方法。
我在这里正确吗?有没有更简单的方法?
可以编写linq扩展名以跳过导致异常的所有元素,并允许您传递操作来处理引发的异常。
public static IEnumerable<T> CatchExceptions<T> (this IEnumerable<T> src, Action<Exception> action = null)
{
using (var enumerator = src.GetEnumerator())
{
bool next = true;
while (next)
{
try
{
next = enumerator.MoveNext();
}
catch (Exception ex)
{
if (action != null)
action(ex);
continue;
}
if (next)
yield return enumerator.Current;
}
}
}
如果您想做的是在处理枚举结果的过程中处理异常,那么您尝试逻辑只需要直接在for / while循环内进行。