代码之家  ›  专栏  ›  技术社区  ›  Vinko Vrsalovic

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

  •  7
  • Vinko Vrsalovic  · 技术社区  · 14 年前

    我正在处理一些类,这些类在抛出时有一个相对较深的内部感觉树。我想记录并处理最内部的异常情况,这是造成问题的真正原因。

    我目前正在使用类似于

    public static Exception getInnermostException(Exception e) {
        while (e.InnerException != null) {
            e = e.InnerException;
        }
        return e;
    }
    

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

    4 回复  |  直到 9 年前
        1
  •  10
  •   Vinko Vrsalovic    14 年前

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

    public static Exception getInnermostException(Exception e) { 
        return e.GetBaseException(); 
    }
    
        2
  •  3
  •   AdaTheDev    14 年前

    你可以用 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());
    }
    
        3
  •  0
  •   Quick Joe Smith    14 年前

    总之,是的。我想不出任何明显更好或不同的方法。除非你想把它作为一个扩展方法来添加,但是它实际上是一个方法中的六个,另一个方法中的六个。

        4
  •  0
  •   kat    9 年前

    有些异常可能有多个根本原因(例如 AggregateException ReflectionTypeLoadException )

    我自己创造了 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;
    }