Why doesn't System.Exception.ToString call virtual ToString for inner exceptions?

孤者浪人 提交于 2021-02-18 21:10:41

问题


This is the actual source for .NET's 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;
}

Apart from the sheer ugliness, one can notice that for all inner exceptions the private, non-virtual ToString will be called. In other words, if you overload ToString in your exception it won't get called if your exception happens to be nested. Oh, hold on, turns out built-in exceptions have same problems, e.g. System.IO.FileNotFoundException prints out path of the file - it is not a part of the Message:

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
    });
  ...
}

But if you wrap an instance... this information will be lost, unless you traverse the exceptions tree yourself and detect exceptions' type or call ToString yourself and do some mundane parsing.

That's an annoying inconvenience, making logging/writing error dialogs either lose information or being bug-prone. Interestingly, Mono gets it right.

Is there any hidden wisdom in .NET's version?

EDIT: this is not opinion based question. While I find this design choice annoying, I would like to know the benefits of this approach. Knowing them may be beneficial when desiging new solutions.


回答1:


Exception.ToString() is not something that should be presented to users. It is something that should be presented to developers, perhaps in a log file.

The default implementation of ToString() normally does the "right thing". Notice how it does handle nested exceptions, and multiple exceptions (like AggregateException or SqlException), and even exceptions across a remoting boundary. Try getting an error during the deserialization of XML with the XML serializer, and you'll really appreciate how much information it gives you - usually enough to point directly to the cause of the exception.

If there is something specific that you would like to see displayed, then you should engage Microsoft on this issue. In particular, you're not likely to get them to simply call your overridden ToString. Clearly, the do not want to. However, if there is something your ToString wanted to display that theirs does not, then talk to them and see if there's another way to go about it, or if there's something they can do in a future release.




回答2:


In my experience, not including the inner exception details in the call to ToString is the correct decision by the framework designers.

Often, the result of ToString is presented to the end user in the event that the executing application cannot provide the user with more precise information on the nature of the problem and possible solutions.

In this case, nesting internal exception details can not only be confusing to the end user, it could also present a potential security risk. The example of the file name problem above is a good one: I would not want to expose the directory information of a file on my web server to an external user in the event the file could not be found (in theory, the exception would always be correctly handled to prevent this exposure, but no application is perfect).

Where the inner exception details become useful is in logging the application fault somewhere (event log, file, database, etc.). In this case, you will most likely want more than just the ToString details, so the implication is that since you have to have logging code for these situations anyway, this logging code is what is responsible for extracting the appropriate information.

I believe that Microsoft realized this early on since one of the first Application Blocks that they added to their Enterprise Library was the Exception Handling block, which provides an in-depth traversal and recording of all exception details, including public properties on the exceptions themselves.



来源:https://stackoverflow.com/questions/20601776/why-doesnt-system-exception-tostring-call-virtual-tostring-for-inner-exceptions

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!