C#:覆盖自定义异常的ToString()方法

Igo*_*ejc 23 .net c# exception tostring

我有一个自定义异常类,其中包含一些其他字段.我希望在ToString()方法中写出这些,但如果我实现自己的ToString(),我会放弃一些其他有用的东西(比如编写异常类型名称,内部异常数据和堆栈跟踪).

ToString()为此类异常实现自己的方法的最佳方法/模式是什么?理想情况下,它应该重用现有机制,但格式与默认ToString()实现类似.

更新:将我的自定义字段前置或附加到base.ToString()文本不是理想的恕我直言,例如

PimTool.Utilities.OERestServiceUnavailableException: test ---> System.InvalidOperationException: inner message
   --- End of inner exception stack trace ---
   at PimTool.Tests.Services.OE.OERestClientTests.ExceptionsLogging() in D:\svn\NewPimTool\PimTool.Tests\Services\OE\OERestClientTests.cs:line 178, 
   StatusCode=0, message='test', requestId='535345'
Run Code Online (Sandbox Code Playgroud)

表示自定义字段写在(可能很长)的异常描述的末尾.另一方面,我希望异常类型是描述中写的第一个信息.

更新2:我已经为此实现了一个解决方案,请在下面查找我自己的答案.

Dar*_*ryl 29

这都是矫枉过正的.您的异常应该覆盖Message Property.

public override String Message {
    get {  
        return base.Message + String.Format(", HttpStatusCode={0}, RequestId='{1}'", 
                    httpStatusCode, 
                    RequestId);
    }
}
Run Code Online (Sandbox Code Playgroud)

Exception类的默认ToString方法基本上是" ClassName: Message --> InnerException.ToString() StackTrace".因此,覆盖Message会将消息文本准确地放在应有的位置.

  • 这很有效,但我不确定它是不是很好的风格,至少可能并不总是这样,因为“Message”属性并不限于“ToString”的使用。`new CustomException("My message").Message` 返回字符串 `!= "My message"` 可能会出乎意料。如果某人想在某处显示/记录他们的消息而不是附加信息,并假设“消息”等于他们设置的消息,那么这可能会咬住某人。并不是说这种做法不对,而是要具体情况具体分析。 (2认同)

Kon*_*man 13

您可以ToString通过查看异常属性手动将默认数据添加到返回的字符串中.例如,以下内容将模拟异常ToString方法默认返回的数据(假设没有内部异常):

string.Format("{0}: {1}\r\n{2}", this.GetType().Name, this.Message, this.StackTrace);
Run Code Online (Sandbox Code Playgroud)

或者,您只需将返回的数据附加(或预先添加)base.ToString到您要添加的信息即可.

  • 这似乎是我想到的最接近的解决方案。虽然你忘记写出 InnerException ;) (2认同)

Igo*_*ejc 12

好的,这就是我提出的.我已经实现了一个扩展类,它复制了格式化异常的原始机制,但有一个转折点:一个自定义Action委托,它提供了一个用于格式化自定义字段的插件:

public static class ExceptionFormatterExtensions
{
    public static string ExceptionToString (
        this Exception ex, 
        Action<StringBuilder> customFieldsFormatterAction)
    {
        StringBuilder description = new StringBuilder();
        description.AppendFormat("{0}: {1}", ex.GetType().Name, ex.Message);

        if (customFieldsFormatterAction != null)
            customFieldsFormatterAction(description);

        if (ex.InnerException != null)
        {
            description.AppendFormat(" ---> {0}", ex.InnerException);
            description.AppendFormat(
                "{0}   --- End of inner exception stack trace ---{0}",
                Environment.NewLine);
        }

        description.Append(ex.StackTrace);

        return description.ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以在自己的ToString()实现中使用此方法,而无需复制格式代码:

    public override string ToString()
    {
        return this.ExceptionToString(
            description =>
            {
                description.AppendFormat(
                    ", HttpStatusCode={0}, RequestId='{1}'", 
                    httpStatusCode, 
                    RequestId);
            });
    }
Run Code Online (Sandbox Code Playgroud)


Chr*_*tow 10

您可以覆盖ToString()方法以包含您自己的自定义信息,并仍然像这样调用默认基础Exception ToString():

public class MyException : Exception
{
    public string CustomField { get; set; }
    public override string ToString()
    {
        return CustomField + Environment.NewLine + base.ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)


And*_*ngs 5

如果您主要在调试器中查看它们,那么您可以使用该[DebuggerDisplay]属性来指定它们的格式,而不需要触及现有的ToString方法。

否则,只需重载ToString并确保调用基类版本base.ToString()