2010-08-19 34 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