您的初始代码应该可以正常工作。您不应该丢失字典条目。
[编辑]:详细说明。
让我们看下面的示例代码:
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
方法中所做的那样。