修改其Dictionary后抛出异常

时间:2013-08-20 15:35:32

标签: c# exception-handling throw catch-block rethrow

以下是我在C#中的代码:

catch(Exception ex)
{
   ex.Data.Add("VarName", "object");
   throw;
}

问题:如上所述,我是否会丢失我要添加到数据字典中的条目? - >在我看来,我正在重新抛出catch语句中捕获的异常,并且它还没有从下一行添加的Dictionary记录。

上面的代码应该是:

catch(Exception ex)
{
   ex.Data.Add("VarName", "object");
   throw ex;
}
  • 但在这种情况下,我不想重置堆栈跟踪。

在网上和SO上搜索过这个,但没有运气。

TIA!

1 个答案:

答案 0 :(得分:3)

您的初始代码应该可以正常工作。你不应该丢失字典条目。

[编辑] :详细说明。

我们来看下面的示例代码:

using System;
class Program
{
    static void Main()
    {
        Change();
        Replace();
        Inner();
    }

    static void Change()
    {
        try {
            try {
                throw new Exception("This is a message");
            } catch (Exception e) {
                e.Data.Add("foo", "bar");
                throw;
            }
        } catch (Exception e) {
            System.Diagnostics.Trace.WriteLine(e.Message);
            System.Diagnostics.Trace.WriteLine(e.Data["foo"]);
        }
    }

    static void Replace()
    {
        try {
            try {
                throw new Exception("This is a message");
            } catch (Exception e) {
                e = new Exception("Different message", e);
                e.Data.Add("foo", "bar");
                throw;
            }
        } catch (Exception e) {
            System.Diagnostics.Trace.WriteLine(e.Message);
            System.Diagnostics.Trace.WriteLine(e.Data["foo"]);
        }
    }

    static void Inner()
    {
        try {
            try {
                throw new Exception("This is a message");
            } catch (Exception e) {
                e.Data.Add("foo1", "bar1");
                e = new Exception("Different message", e);
                e.Data.Add("foo2", "bar2");
                throw e;
            }
        } catch (Exception e) {
            System.Diagnostics.Trace.WriteLine(e.Message);
            System.Diagnostics.Trace.WriteLine(e.Data["foo2"]);
            System.Diagnostics.Trace.WriteLine(e.InnerException.Message);
            System.Diagnostics.Trace.WriteLine(e.InnerException.Data["foo1"]);
        }
    }
}

抛出Exception时,真正引发的是对Exception对象的引用。该引用是被捕获和重新引发的内容。修改底层对象很好。这是您的初始代码所做的,以及我的示例中的Change方法。

Replace方法中,我们不是修改对象,而是修改引用本身。我们将它指向一个全新的Exception对象,其中包含不同的消息,最重要的是我们还添加了一些数据。但是,所有这些东西都丢失了,因为没有参数的throw会重新抛出原始引用。

如果需要使用第二种情况,您可以通过将原始异常包含在InnerException中来跟踪堆栈跟踪,就像我在Inner方法中所做的那样。