4

Is there a way to override the message of an exception?
I don't want to make a custom exception but to override the message of an existing exception.
For example: Every time when a ArgumentOutOfRangeException is thrown, I'd like it to contain my message instead of the default one.

Is it possible?

Idov
  • 5,006
  • 17
  • 69
  • 106

3 Answers3

10

For exceptions you're throwing, you can just pass the message in to the constructor:

throw new ArgumentOutOfRangeException("name", "My custom message");

Note that here, name is the name of the parameter that caused the problem. In C# 6, you should use the nameof operator to make this refactoring-safe:

public void Foo(int x)
{
    if (x > 10)
    {
        throw new ArgumentOutOfRangeException(nameof(x), "That's too big");
    }
}

You can't modify the message of an exception thrown by other code, but you can catch the exception and rethrow another one:

try
{
    ...
}
catch (FooException e)
{
    // Keep the original exception
    throw new BarException("Some message", e);
}

I would try to avoid doing this too much though. If you're considering showing exception messages to users, I would generally shy away from that - they're really aimed at developers. As an example, the ArgumentOutOfRangeException you suggested should generally indicate a bug in your code rather than some external condition (like a network failure or whatever) - the user isn't going to be able to do anything about that bug; it's something you should fix. A network failure or something similar is at least more reasonable for the user to take action about, but frankly it's often not going to be clear what the chain of events is.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    @Idov: Well that's a completely matter. Will edit. (It would help if you could be clearer in the question...) – Jon Skeet Jul 14 '15 at 06:15
  • `You can't modify the message of an exception thrown by other code` - actually, in that case you can, because message string being taken from resource for specific culture. The tricky part is to override CLR default culture and I don't think it's worth effort. – cyberj0g Jul 14 '15 at 06:23
  • @cyberj0g: Not after the exception has been, created, I mean. – Jon Skeet Jul 14 '15 at 06:24
  • 1
    @JonSkeet You mentioned it isn't advised to rethrow (meaning changing the exception type of) exceptions so the user can understand their contexts. But is it developer practice to change the exception type to indicate why it was thrown (for other developers)? For instance, an exception thrown by some class method might be `IndexOutOfRangeException (IOORE)` (referring to invalid access of an underlying data structure) but if I knew why it was thrown, perhaps because the object state was improperly set, should I catch `IOORE` and rethrow `InvalidOperationExpeption` with a custom message? – Minh Tran Jan 17 '20 at 18:53
  • @JonSkeet I've added an example [here](https://stackoverflow.com/a/178464/3396951) of what I mean. – Minh Tran Jan 17 '20 at 20:22
  • @MinhTran: Usually if you can anticipate why a particular exception will be thrown, you can avoid it happening in the first place. Also note that I only suggest avoiding doing this **too much** - that's quite different to saying "it isn't advised to rethrow". There are places where I'll do that, but I'll always think carefully before doing so. – Jon Skeet Jan 17 '20 at 23:06
3

The Exception.Message property is declared read-only, so no, you cannot change the Message of a pre-existing Exception object. (The same applies to derived exception types.)

But you can set the message text of an exception you're throw-ing yourself: usually, you pass the message text to the exception constructor:

throw new ArgumentException("Frobbled arguments are not accepted", paramName: …);
//                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

When you define your own exception types, you should follow this protocol; see the section at the end of this answer.

You want to change an existing exception object's Message — Alternatives:

  • Catch the original exception and derive a new exception from it that is identical except for the message:

    …
    catch (ArgumentException ex)
    {
        throw new ArgumentException("New message text", paramName: ex.ParamName);
    }
    

    This is in general not a terribly good idea, because you might lose state data contained in ex (such as its stack trace and InnerException). But it might work just fine in this scenario.

  • Wrap the exception in a new exception so that it becomes the InnerException:

    …
    catch (ArgumentException ex)
    {
        throw new ArgumentException("New message text", innerException: ex);
    }
    

    This is better, because all the original exception's state is preserved. However, in the particular case of ArgumentException it is not obvious at all that the actual exception information is contained in the InnerException.

How to make sure your own exception classes allow setting the message et al.:

When you define a new exception type, it's important for the reasons mentioned above to define constructors that accept a message text and/or an inner exception. So a custom exception class would have at least these constructors:

class MyCustomException : Exception
{
    public MyCustomException() : base() { }
    public MyCustomException(string message) : base(message) { }
    public MyCustomException(string message, Exception innerException) : base(message, innerException) { }
    public MyCustomException(string message) : base(message) { }
}
stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
0

You can use try .. . catch

        try
        {
            //Code here regarding array indexing
        }
        catch (ArgumentOutOfRangeException ex)
        {
            throw new ArgumentOutOfRangeException("exception", "New Custom Message");
            //Or show new message
            MessageBox.Show("Your custom Message");
        } 
NASSER
  • 5,900
  • 7
  • 38
  • 57