82

I want to make a custom Exception in C#, but in theory I do need to do a little parsing first before I can make a human readable ExceptionMessage.

The problem is that the orginal Message can only be set by calling the base constructor of Messsage, so I can't do any parsing in advance.

I tried overring the Message property like this:

public class CustomException : Exception
{
    string _Message;

    public CustomException(dynamic json) : base("Plep")
    {
        // Some parsing to create a human readable message (simplified)
        _Message    = json.message;
    }

    public override string Message
    {
        get { return _Message; }
    }
}

The problem is that the Visual Studio debugger still shows the message that I've passed into the constructor, Plep in this case.

throw new CustomException( new { message="Show this message" } )

results in:

Visual Studio Exception Dialog

If I leave the base constructor empty it will show a very generic message:

An unhandled exception of type 'App.CustomException' occurred in App.exe

Question

It looks like the Exception Dialog reads some field/property that I don't have any access too. Is there any other way to set a human readable error message outside the base constructor on Exception.

Note that I'm using Visual Studio 2012.

5
  • Your code worked just fine for me. and it sould work.
    – Swift
    Commented Jul 24, 2013 at 10:01
  • It compiles, but if you throw an error it will show the underlying Message ("Plep"), instead of "Show this message". Please take a look at the extra example that I've added.
    – Dirk Boer
    Commented Jul 24, 2013 at 10:17
  • I think the ideal solution is not available. I went to a similar problem when I parsed the wholoe Exception classes to JSON. Custom properties are lost in the process. Can you describe a scenario? Perhaps we can help with some workaround.
    – Minduca
    Commented Jul 24, 2013 at 10:35
  • I tried to throw the exception and I had the custom message that I put and not Pllep
    – Swift
    Commented Jul 24, 2013 at 10:43
  • Houssem, what IDE are you using? Are you looking at the same debugger dialog?
    – Dirk Boer
    Commented Jul 24, 2013 at 14:10

5 Answers 5

139
+50

Just put the formatting code into a static method?

public CustomException(dynamic json) : base(HumanReadable(json)) {}
private static string HumanReadable(dynamic json) {
    return whatever you need to;
}
1
  • 5
    Perfect! Wasn't even aware that you could actually call a static method inside the arguments section of the base constructor!
    – Dirk Boer
    Commented Jul 24, 2013 at 14:12
26

Consider the Microsoft Guidelines for creating new exceptions:

  using System;
  using System.Runtime.Serialization;

  [Serializable]
  public class CustomException : Exception
  {
    //
    // For guidelines regarding the creation of new exception types, see
    //    https://msdn.microsoft.com/en-us/library/ms229064(v=vs.100).aspx
    //

    public CustomException()
    {
    }

    public CustomException(string message) : base(message)
    {
    }

    public CustomException(string message, Exception inner) : base(message, inner)
    {
    }

    protected CustomException(SerializationInfo info, StreamingContext context) : base(info, context)
    {
    }

    public static CustomException FromJson(dynamic json)
    {
      string text = ""; // parse from json here

      return new CustomException(text);
    }
  }

Note the static factory method (not part of the pattern), that you can use in your program like this:

throw CustomException.FromJson(variable);

That way you followed best practice and can parse your json inside the exception class.

2
  • 6
    This would work.. but in a way you are still working around the standards . I've never thrown an Exception by invoking a static method - the default .NET exceptions also don't have a static method to invoke them. I rather won't do this, because it is not very discoverable for other programmers.
    – Dirk Boer
    Commented Jul 17, 2013 at 9:23
  • 2
    Both links in the comment are broken. New link: Design Guidelines for Exceptions Commented Mar 21, 2016 at 13:38
11

What's wrong with something like this.

    public class FolderNotEmptyException : Exception
{

    public FolderNotEmptyException(string Path) : base($"Directory is not empty. '{Path}'.")
    { }

    public FolderNotEmptyException(string Path, Exception InnerException) : base($"Directory is not empty. '{Path}'.", InnerException)
    { }

}

I just use a string and include parameters. Simple solution.

2
  • doing that, we throw away the ability to overwrite the exception message from the thrower.
    – Dinh Tran
    Commented Mar 29 at 4:02
  • It is setting the message for you. This is the standard way to create exceptions. You can always create another constructor that takes an explicit message and move the path to a property. This is only a reference implementation, and editing may be required to suit your needs, Not every bit of code on here should just be copy & pasted. Commented Mar 29 at 20:10
9

I think the problem may be with the Visual Studio debugger. I got the same exact results you got using the debugger, but when I print the message instead:

class CustomException : Exception {
    public CustomException(dynamic json)
        : base("Plep") {
            _Message = json.message;
    }

    public override string Message {
        get { return _Message; }
    }

    private string _Message;
}

class Program {
    static void Main(string[] args) {
        try {
            throw new CustomException(new { message = "Show this message" });
        } catch (Exception ex) {
            Console.WriteLine(ex.Message);
        }
    }
}

I get the expected "Show this message".

If you put a breakpoint where the Exception is caught, the debugger does show you the correct message.

1
  • 1
    I know, but the problem is indeed about the dialog that the Visual Studio debugger showed (see screenshot). Just got tired (and thought it was pretty ugly) to constantly look at the internal Exception or other ways to view the original message.
    – Dirk Boer
    Commented Jul 24, 2013 at 14:08
7

I like to use this here. It is easy and does not need the static function:

public class MyException : Exception
{
    public MyException () : base("This is my Custom Exception Message")
    {
    }
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.