2013-12-16 16 views
8

這是.NET的System.Exception.ToString實際來源:爲什麼System.Exception.ToString爲內部異常調用虛擬ToString?

public override string ToString() 
{ 
    return this.ToString(true, true); 
} 

private string ToString(bool needFileLineInfo, bool needMessage) 
{ 
    string str1 = needMessage ? this.Message : (string) null; 
    string str2 = str1 == null || str1.Length <= 0 ? this.GetClassName() : this.GetClassName() + ": " + str1; 
    if (this._innerException != null) 
    str2 = str2 + " ---> " + this._innerException.ToString(needFileLineInfo, needMessage) + Environment.NewLine + " " + Environment.GetRuntimeResourceString("Exception_EndOfInnerExceptionStack"); 
    string stackTrace = this.GetStackTrace(needFileLineInfo); 
    if (stackTrace != null) 
    str2 = str2 + Environment.NewLine + stackTrace; 
    return str2; 
} 

除了純粹的醜陋,人們可以注意到,所有內部異常的私人,非虛擬的ToString將被稱爲。換句話說,如果您在例外中重載ToString,如果您的例外恰好嵌套,它將不會被調用。呵呵,堅持下來,內置的例外有相同的問題,例如System.IO.FileNotFoundException打印出的文件的路徑 - 它是不是消息的一部分:

public override string ToString() 
{ 
    string str = this.GetType().FullName + ": " + this.Message; 
    if (this._fileName != null && this._fileName.Length != 0) 
    str = str + Environment.NewLine + Environment.GetResourceString("IO.FileName_Name", new object[1] 
    { 
     (object) this._fileName 
    }); 
    ... 
} 

但如果你換一個實例......這些信息將會丟失,除非你自己遍歷例外樹和檢測例外請自己輸入或撥打ToString並進行一些普通的解析。

這是一個惱人的不便,使得記錄/寫入錯誤對話框或者丟失信息或成爲容易出錯。有趣的是,Mono gets it right

.NET版本中有沒有隱藏的智慧?

編輯:這不是基於意見的問題。雖然我覺得這個設計選擇令人討厭,但我想知道這種方法的好處。在設計新的解決方案時瞭解它們可能是有益的。

回答

1

以我的經驗,不包括在調用的ToString內部異常的詳細信息是由框架設計師是正確的決定。

通常,的ToString的結果呈現給在事件執行的應用不能提供有關問題和可能的解決方案的性質更精確的信息的用戶的最終用戶。

在這種情況下,嵌套內部異常的細節不僅可以混淆到最終用戶,它也可能存在潛在的安全風險。上面的文件名問題的例子是一個很好的例子:我不想在我的web服務器上的文件的目錄信息暴露給外部用戶,如果找不到文件(理論上,正確處理以防止這種暴露,但沒有應用是完美的)。

凡內異常細節成材是在什麼地方登錄應用程序故障(事件日誌,文件,數據庫等)。在這種情況下,你很可能不僅僅需要ToString細節,所以暗示是因爲無論如何你必須爲這些情況記錄代碼,這個日誌代碼就是負責提取適當信息的東西。

我相信微軟早就意識到了這一點,因爲他們添加到企業庫中的第一個應用程序塊之一是Exception Handling block,它提供了對所有異常詳細信息的深入遍歷和記錄,包括對異常的公共屬性他們自己。

+0

我明白你的觀點,但要注意向用戶呈現異常堆棧和/或調用堆棧可能是一個安全性問題。更不用說,默認的'ToString'也會打印'Message'屬性,它可能包含有意義的數據。因此,如果這是微軟的設計決策,它最終會成爲一個既不符合安全性又不符合信息性的中間環境。對於「零售」程序,您根本不應顯示「ToString」的結果,對於內部技術,您需要更多信息(它就在那裏!)。 – gwiazdorrr

2

Exception.ToString()是不是應該呈現給用戶。它應該提交給開發人員的東西,可能在日誌文件中。

ToString()的默認實現通常會做「正確的事情」。注意它是如何處理嵌套異常和多個異常(如AggregateExceptionSqlException),甚至跨越遠程邊界的異常。嘗試在使用XML序列化器對XML進行反序列化時出現錯誤,並且您會非常感謝它提供了多少信息 - 通常足以直接指向異常的原因。

如果有什麼特定的內容希望顯示,那麼您應該就此問題與Microsoft聯繫。特別是,你不可能讓他們簡單地調用你重寫的ToString。顯然,不想。但是,如果ToString想顯示他們沒有顯示的東西,那麼請與他們交談,看看是否還有其他方法可以解決這個問題,或者他們在將來的版本中可以做些什麼。