Search code examples
c#.netexceptiontostring

C#: Overriding ToString() method for custom exceptions


I have a custom exception class which contains some additional fields. I want these to be written out in the ToString() method, but if I implement my own ToString(), I loose some other useful stuff (like writing the exception type name, the inner exception data and the stack trace).

What is the best way/pattern to implement your own ToString() method for such exceptions? Ideally it should reuse the existing mechanism, but be formatted in way similar to the default ToString() implementation.

UPDATE: prepending or appending my custom fields to the base.ToString() text isn't ideal IMHO, for example

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'

means the custom fields are written at the end of the (potentially long) exception description. On the other hand, I want the exception type to be the first information written in the description.

UPDATE 2: I've implemented a solution for this, look for my own answer below.


Solution

  • OK, this is what I came up with. I've implemented an extension class which replicates the original mechanism for formatting exceptions, but with a twist: a custom Action delegate which provides a plug-in for formatting custom fields:

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

    Now you can use this method in your own ToString() implementations without duplicating the formatting code:

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