2010-08-19 32 views
3

当我在做一个项目时,我想我自己:“嗯,记录一条消息会非常方便,然后用同样的消息抛出一个异常。由于这会让我保留我的“例外情况是出于特殊情况”原则,但仍然确保我们记录有关系统中出现问题的详细信息。CLR在'throw'上做了什么?

这样就产生了:

public static class LogAndThrow 
{ 
    public static void Message<TException>(string message) where TException : Exception 
    { 
     // Log message here 

     var constructor = 
      typeof(TException).GetConstructor(new[] { typeof(string) }); 

     throw (TException)constructor.Invoke(new[] { message }); 
    } 
} 

相信这是一个有点粗糙(我剪下来的这个帖子),但它的作品。

然而,作为通过反射来构建异常的人的类型,我很烦恼堆栈跟踪会被LogAndThrow.Message()行“污染”。

所以我掀起来修复:-)

我能够与一些系列化和其他弄虚作假,都非常愚蠢和力量,以取代堆栈跟踪。但我想知道这一点,因为。

但我注意到了一些好奇:

var exception = new Exception(); 
throw exception; 

创建该异常后,却抛出之前,唯一集消息。堆栈跟踪等是空的。

以上是等同于以下IL:

.locals init (
    [0] class [mscorlib]System.Exception exception) 
nop 
newobj instance void [mscorlib]System.Exception::.ctor() 
stloc.0 
ldloc.0 
throw 

这似乎对我来说,IL为“扔”在做一些事情不仅仅是采取这一参考,并走它的堆栈更多。

有没有人知道当IL'throw'到达时,运行时正在执行堆栈上的异常吗?

我们将在下面用来改变堆栈中抛出涉及“神奇”的诀窍,我认为:

此代码是可怕的和错误的。更多的科学实验比任何应该永远放在evereververEVER

var e = new Exception("message here"); 
try 
{ 
    throw e; 
} 
finally 
{ 
    // Get the private file _stackTraceString with reflection 
    field.SetValue(e, new StackTrace(1).ToString()); 
} 
+0

为什么在'catch'中通过'throw e;'重新抛出异常是不好的 - 它会修改关于对象中堆栈跟踪的属性。 – IllidanS4 2016-12-01 21:17:57

回答

5

你为什么不能修改的静态方法返回一个异常对象,后来投入生产的。例如

// Do something 
... 
// Found error condition, need to throw an exception 
if (error condition) 
{ 
    throw LogAndThrow.Message("Message goes here"); 
} 

编辑:AFAIK,没有办法修改堆栈跟踪。有些方法可以保留原始堆栈跟踪,同时重新抛出异常 - 请参阅此article

另一个编辑

只是想,我会放一些额外的信息&链接。基本上,只有在引发异常时,CLR才会在异常对象中构建堆栈跟踪。这在MSDN被提到 - 引自MSDN:

公共语言运行时(CLR)(通过使用throw关键字)更新每当 异常在应用程序代码中抛出的堆栈跟踪。 如果在与最初抛出异常的方法不同的方法中重新抛出异常,则堆栈跟踪同时包含 方法中最初抛出异常的位置, 以及方法中存在异常的位置被重新抛弃。如果 抛出异常,后来又重新抛出,以同样的方法,将 堆栈跟踪只包含其中的例外是 重新抛出,不包括其中的例外是 最初抛出

此位置的位置也提到了here(其中作者提到CLR在遇到托管代码中的异常时会执行粘连行为)。

在有些相关的说明中(但有点偏离主题),请参阅this excellent article(带有示例代码),其中作者构建备用堆栈跟踪信息(基本上,他从非标准位置查找调试信息)。

+0

这的确是可行的。我想要的是更具说明性的东西。 LogAndThrow.ErrorIf(condition,“blah”); 我前进的方向可能与您的建议相似。 但我仍然好奇虚拟机在这个级别上做了什么:-) – ecoffey 2010-08-20 13:38:30