As you say yourself it has nothing to do with MessageBox
, it depends on the implementation of the ToString()
method.
For example looking at struct Nullable<T> where T : struct
from System.Runtime
that a nullable enum uses as example:
[Serializable]
[NonVersionable] // This only applies to field layout
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public partial struct Nullable<T> where T : struct
It's implementation of ToString()
looks like this for .NET 7:
public override string? ToString() => hasValue ? value.ToString() : "";
Therefore the following code gives an exception on MessageBox.Show(s.ToString());
even though ToString()
is called on a null object for tc.TestEnum
.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var tc = new TestClass();
MessageBox.Show(tc.TestEnum.ToString());
string s = null;
MessageBox.Show(s);
MessageBox.Show(s.ToString());
}
}
public enum TestEnum
{
None = 0
}
public class TestClass
{
public TestEnum? TestEnum { get; set; }
}
System.NullReferenceException: 'Object reference not set to an
instance of an object.'
Looking at class String
from System.Runtime
:
[Serializable]
[NonVersionable] // This only applies to field layout
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public sealed partial class String : IComparable, IEnumerable, IConvertible, IEnumerable<char>, IComparable<string?>, IEquatable<string?>, ICloneable
Here we have another implementation that will throw the error you see:
// Returns this string.
public override string ToString()
{
return this;
}
However starting with .NET 6<
<Nullable>enable</Nullable>
is enabled by default for new projects.
https://learn.microsoft.com/en-us/dotnet/csharp/nullable-references
The code above will therefore give you two warnings:
string s = null;
-> CS8600 Converting null literal or possible null value to non-nullable type.
MessageBox.Show(s.ToString());
-> CS8602 Dereference of a possibly null reference
Rewrite the code like this and the errors disappear:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var tc = new TestClass();
MessageBox.Show(tc.TestEnum.ToString());
string? s = null;
MessageBox.Show(s);
if (s is not null)
{
MessageBox.Show(s.ToString());
}
}
}
public enum TestEnum
{
None = 0
}
public class TestClass
{
public TestEnum? TestEnum { get; set; }
}
Or simply using the null-conditional operator ?.
like @mr R writes:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var tc = new TestClass();
MessageBox.Show(tc.TestEnum.ToString());
string? s = null;
MessageBox.Show(s);
MessageBox.Show(s?.ToString());
}
}
public enum TestEnum
{
None = 0
}
public class TestClass
{
public TestEnum? TestEnum { get; set; }
}
null
damage on a string or object,obj?.ToString() ?? ""
– Sioux