包装IEnumerable并捕获异常

问题描述 投票:10回答:5

我有一堆可以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;
    }
}

但是那比我希望的要复杂,而且我不能完全确定它的正确性还是没有更简单的方法。

我在这里正确吗?有没有更简单的方法?

c# exception ienumerable wrapper
5个回答
6
投票

可以编写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;
        }
    }
}

5
投票

如果您想做的是在处理枚举结果的过程中处理异常,那么您尝试逻辑只需要直接在for / while循环内进行。


0
投票

-1
投票

-2
投票
© www.soinside.com 2019 - 2024. All rights reserved.