单声道:如何(重新)抛出异常保留原始堆栈跟踪信息并收集本地数据

时间:2014-04-30 16:34:02

标签: c# exception exception-handling mono callstack

我递归处理分层数据。如果出现问题,我想在堆栈展开时收集额外的信息(导致异常的节点的路径)。我想保留原始异常消息和堆栈跟踪。这应该是非常受欢迎的任务,但我在.NET中找不到任何支持。我怎么能实现这个呢?

我试图捕获异常并重新抛出我自己的异常,在递归函数中提供额外的数据,或者将其他数据存储在原始异常Exception.Data中。问题是我没有设法提供正确的堆栈跟踪,其中应包括原始异常堆栈跟踪+堆栈跟踪,以便我的递归函数调用展开到我处理异常的地方。

我的代码如下:

void func(...)
{
    try
    {
         ...
         func(...);
    }
    catch (Exception ex)
    {
        Rethrow(ex, localData);
    }
}

Rethrow()如何实施?

修改

我发现这只发生在Mono上,而不是.NET。是的,在.NET throw;中工作正常。在Mono中它没有,至少在我使用的版本中(Unity3D的Mono 2.8的自定义版本)。例如:

    static void CheckRethrow()
    {
        try
        {
            f(0);
        }
        catch (Exception ex)
        {
            Debug.LogException(ex);
        }
    }

    static void f(int i)
    {
        try
        {
            if (i > 3)
                throw new Exception("some message");
            f(++i);
        }
        catch (Exception ex)
        {
            throw;
        }
    }

输出调用堆栈:

f (Int32 i) (at Test.cs:18)
CheckRethrow() (at Test.cs:9)

正如您所看到的,此调用堆栈中缺少对f()的几次调用。

2 个答案:

答案 0 :(得分:4)

在.NET中,几乎所有例外都有一个名为InnerException的成员。您可以有多个例外或一系列例外。

void func(...)
{
    try
    {
         ...
         func(...);
    }
    catch (Exception ex)
    {
        throw new MyOwnExceptionWithLocalData(localData, ex);
    }
}

或者,虽然我还没有对它进行测试,但是你可以通过不提变量来为你的异常添加信息并保留它的堆栈跟踪:

void func(...)
{
    try
    {
         ...
         func(...);
    }
    catch (Exception ex)
    {
        ex.Property = value;
        throw; // Note: no variable name here, will throw last exception and preserve stack trace
    }
}

答案 1 :(得分:1)

只需使用按键抛出

try {

} catch (Exception ex){      

    throw;
}