在C#中,如何重新抛出InnerException而不丢失堆栈跟踪?

我通过反思调用了一种可能导致异常的方法。 如何在没有包装反射的情况下将异常传递给我的调用者? 我重新抛出InnerException,但是这破坏了堆栈跟踪。 示例代码:

    public void test1()
    {
        // Throw an exception for testing purposes
        throw new ArgumentException("test1");
    }

    void test2()
    {
        try
        {
            MethodInfo mi = typeof(Program).GetMethod("test1");
            mi.Invoke(this, null);
        }
        catch (TargetInvocationException tiex)
        {
            // Throw the new exception
            throw tiex.InnerException;
        }
    }

.NET 4.5中 ,现在有了ExceptionDispatchInfo类。

这可以让您捕获异常并重新抛出异常,而无需更改堆栈跟踪:

try
{
    task.Wait();
}
catch(AggregateException ex)
{
    ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
}

这适用于任何异常,而不仅仅是AggregateException

它是由于await C#语言功能而引入的,该功能从AggregateException实例中解开内部异常,以使异步语言功能更像同步语言功能。


可能的,而不反射重新抛出之前保存堆栈跟踪:

static void PreserveStackTrace (Exception e)
{
    var ctx = new StreamingContext  (StreamingContextStates.CrossAppDomain) ;
    var mgr = new ObjectManager     (null, ctx) ;
    var si  = new SerializationInfo (e.GetType (), new FormatterConverter ()) ;

    e.GetObjectData    (si, ctx)  ;
    mgr.RegisterObject (e, 1, si) ; // prepare for SetObjectData
    mgr.DoFixups       ()         ; // ObjectManager calls SetObjectData

    // voila, e is unmodified save for _remoteStackTraceString
}

与通过缓存委托调用InternalPreserveStackTrace相比,这会浪费很多周期,但具有仅依赖公共功能的优势。 以下是一些堆栈跟踪保存功能的常用使用模式:

// usage (A): cross-thread invoke, messaging, custom task schedulers etc.
catch (Exception e)
{
    PreserveStackTrace (e) ;

    // store exception to be re-thrown later,
    // possibly in a different thread
    operationResult.Exception = e ;
}

// usage (B): after calling MethodInfo.Invoke() and the like
catch (TargetInvocationException tiex)
{
    PreserveStackTrace (tiex.InnerException) ;

    // unwrap TargetInvocationException, so that typed catch clauses 
    // in library/3rd-party code can work correctly;
    // new stack trace is appended to existing one
    throw tiex.InnerException ;
}

我认为你最好的选择就是把它放在你的catch块中:

throw;

然后再提取内隐感觉。

链接地址: http://www.djcxy.com/p/82435.html

上一篇: In C#, how can I rethrow InnerException without losing stack trace?

下一篇: Javascript exception stack trace