找到最内层异常的正确方法?

时间:2010-01-18 10:07:26

标签: c# exception exception-handling

我正在使用一些类,这些类在抛出时具有相对较深的InnerException树。我想记录并采取最内层的例外情况,这个例外是有问题的真正原因。

我目前正在使用与

类似的东西
public static Exception getInnermostException(Exception e) {
    while (e.InnerException != null) {
        e = e.InnerException;
    }
    return e;
}

这是处理异常树的正确方法吗?

4 个答案:

答案 0 :(得分:11)

我认为你可以使用以下代码获得最内层的异常:

public static Exception getInnermostException(Exception e) { 
    return e.GetBaseException(); 
}

答案 1 :(得分:4)

您可以使用GetBaseException方法。 很快的例子:

try
{
    try
    {
        throw new ArgumentException("Innermost exception");
    }
    catch (Exception ex)
    {
        throw new Exception("Wrapper 1",ex);
    }
}
catch (Exception ex)
{
    // Writes out the ArgumentException details
    Console.WriteLine(ex.GetBaseException().ToString());
}

答案 2 :(得分:0)

总之,是的。我无法想到任何明显更好或不同的方式。除非你想把它作为一种扩展方法添加,但它实际上只有六个,另外六个。

答案 3 :(得分:0)

有些例外可能有多种根本原因(例如AggregateExceptionReflectionTypeLoadException)。

我创建了自己的class来导航树,然后不同的访问者收集所有内容或只是根本原因。样本输出here。相关的代码段如下。

public void Accept(ExceptionVisitor visitor)
{
    Read(this.exception, visitor);
}

private static void Read(Exception ex, ExceptionVisitor visitor)
{
    bool isRoot = ex.InnerException == null;
    if (isRoot)
    {
        visitor.VisitRootCause(ex);
    }

    visitor.Visit(ex);
    visitor.Depth++;

    bool isAggregateException = TestComplexExceptionType<AggregateException>(ex, visitor, aggregateException => aggregateException.InnerExceptions);
    TestComplexExceptionType<ReflectionTypeLoadException>(ex, visitor, reflectionTypeLoadException => reflectionTypeLoadException.LoaderExceptions);

    // aggregate exceptions populate the first element from InnerExceptions, so no need to revisit
    if (!isRoot && !isAggregateException)
    {
        visitor.VisitInnerException(ex.InnerException);
        Read(ex.InnerException, visitor);
    }

    // set the depth back to current context
    visitor.Depth--;
}

private static bool TestComplexExceptionType<T>(Exception ex, ExceptionVisitor visitor, Func<T, IEnumerable<Exception>> siblingEnumerator) where T : Exception
{
    var complexException = ex as T;
    if (complexException == null)
    {
        return false;
    }

    visitor.VisitComplexException(ex);

    foreach (Exception sibling in siblingEnumerator.Invoke(complexException))
    {
        visitor.VisitSiblingInnerException(sibling);
        Read(sibling, visitor);
    }

    return true;
}