Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exception with null message

Tags:

c#

exception

I found that exception message can't be null in C#, and after trying this

 var ex = new Exception(null);
 Console.WriteLine(ex.Message);

I get the following message:

Exception of type 'System.Exception' was thrown.

But, in this case,

 var ex = new Exception(string.Empty);
 Console.WriteLine(ex.Message);

the message is just empty.

How this can be explained? Do you think this is expected behavior?

like image 526
Arsen Mkrtchyan Avatar asked Dec 28 '22 09:12

Arsen Mkrtchyan


2 Answers

The other answers (not including the answer from chopikadze) seem to be based on a misreading of the facts. Neither example is throwing an exception.

Rather, in the first example, the constructed exception ex is providing a message because the value of the constructor's message parameter was null. The message is "an exception of type 'System.Exception' was thrown".

It's a fairly common practice to have some fallback behavior when an object reference is null, so that's "how it can be explained". Whether it is "expected", of course, depends on your expectations.

Throwing exceptions in the course of handling exceptions can be problematic, so the framework designers must have chosen this behavior to reduce this possibility. It would have been a nightmare, frankly, if we all had to cover the possibility that exception messages might be null.

EDIT

The behavior is also documented in the remarks for the Message property: "If no message was supplied to the constructor for the current instance, the system supplies a default message that is formatted using the current system culture."

I looked in the CLI spec and in the C# spec, and I found no mention of a requirement that Message have a non-null return value, so I guess that supports the view that this behavior is a framework design decision.

like image 82
phoog Avatar answered Jan 03 '23 08:01

phoog


Actually constructor doesn't need string, you can absolutely surely use null. This is reflectored part of Exception class:

internal string _message;

public Exception(string message)
{
    this.Init();
    this._message = message;
}


private void Init()
{
    this._message = null;
    this._stackTrace = null;
    this._dynamicMethods = null;
    this.HResult = -2146233088;
    this._xcode = -532462766;
    this._xptrs = IntPtr.Zero;
    this._watsonBuckets = null;
    this._ipForWatsonBuckets = UIntPtr.Zero;
    this._safeSerializationManager = new SafeSerializationManager();
}

public virtual string Message
{
    [SecuritySafeCritical]
    get
    {
        if (this._message != null)
        {
            return this._message;
        }
        if (this._className == null)
        {
            this._className = this.GetClassName();
        }
        return Environment.GetRuntimeResourceString("Exception_WasThrown", new object[] { this._className });
    }
}

So if you use null as message in constructor, localized string like "Exception of type 'System.Exception' was thrown." will be used as Message. It means - there is still your Exception, not another one, but it's property Message returns another (calculated) value instead of null from constructor.

I think that it's defined by design (and maybe is used in another places) that Exception.Message should be always not null. So if we want to allow developers use default constructor for Exception class (for example, for using with reflection or for allowing to populate properties later) but we also want to has Message always not null - we should wrap Message with something. I think, one of the possible place of Message usage is default dialog box showed after exception occurs. This way there could be used just Message property, instead of checking - is Message property equals to null etc.

like image 41
chopikadze Avatar answered Jan 03 '23 07:01

chopikadze