这是.NET的实际来源System.Exception.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;
}
Run Code Online (Sandbox Code Playgroud)
除了纯粹的丑陋之外,人们可以注意到,对于所有内部异常,将调用私有的非虚拟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
});
...
}
Run Code Online (Sandbox Code Playgroud)
但是如果你包装一个实例......这个信息将会丢失,除非你自己遍历异常树并检测异常的类型或者ToString
自己调用并做一些普通的解析.
这是令人烦恼的不便,使得记录/写入错误对话框丢失信息或容易出错.有趣的是,Mono做对了.
在.NET的版本中有任何隐藏的智慧吗?
编辑:这不是基于意见的问题.虽然我觉得这个设计选择很烦人,但我想知道这种方法的好处.在设计新的解决方案时,了解它们可能是有益的.
根据我的经验,在对 ToString 的调用中不包括内部异常详细信息是框架设计者的正确决定。
通常,如果执行的应用程序无法向用户提供有关问题性质和可能解决方案的更精确信息,则 ToString 的结果会呈现给最终用户。
在这种情况下,嵌套内部异常详细信息不仅会让最终用户感到困惑,还可能带来潜在的安全风险。上面的文件名问题的例子是一个很好的例子:如果找不到文件,我不想将 Web 服务器上的文件的目录信息暴露给外部用户(理论上,例外总是会发生)正确处理以防止这种暴露,但没有任何应用程序是完美的)。
内部异常详细信息变得有用的地方是在某处(事件日志、文件、数据库等)记录应用程序错误。在这种情况下,您很可能需要的不仅仅是 ToString 详细信息,因此这意味着,由于无论如何您都必须有针对这些情况的日志记录代码,因此该日志记录代码负责提取适当的信息。
我相信微软很早就意识到了这一点,因为他们添加到企业库中的第一个应用程序块是异常处理块,它提供了所有异常详细信息的深入遍历和记录,包括异常本身的公共属性。