ToString on null string
Asked Answered
K

10

37

Why does the second one of these produce an exception while the first one doesn't?

string s = null;
MessageBox.Show(s);
MessageBox.Show(s.ToString());

Updated - the exception I can understand, the puzzling bit (to me) is why the first part doesn't show an exception. This isn't anything to do with the Messagebox, as illustrated below.

Eg :

string s = null, msg;
msg = "Message is " + s; //no error
msg = "Message is " + s.ToString(); //error

The first part appears to be implicitly converting a null to a blank string.

Kisumu answered 25/1, 2011 at 12:39 Comment(3)
The safe way to do- see How to do ToString for a possibly null object?Cold
To avoid null damage on a string or object, obj?.ToString() ?? ""Sioux
For second line, the error happens because you invoke a method (.ToString()) on a null string reference. This is why you get an exception.Reenter
R
31

because you cannot call instance method ToString() on a null reference.

And MessageBox.Show() is probably implemented to ignore null and print out empty message box.

Roentgenoscope answered 25/1, 2011 at 12:42 Comment(1)
First bit is fine, but I think the MessageBox bit of my question is distracting, hence my update.Kisumu
T
15

As this question ranks quite high on Google for a search for "c# toString null", I would like to add that the Convert.ToString(null) method would return an empty a null string, which is ignored by the messagebox.

However, just to reaffirm the other answers, you can use string.Concat("string", null) in this example.

Edit - modified answer in line with HeyJude's comment below. As pointed out, a method like Convert.ToString(null).Length will throw an exception.

Touzle answered 26/2, 2018 at 10:43 Comment(2)
Convert.ToString(null) returns a null value, not an empty string (this can be verified by calling Convert.ToString(null) == null, which returns true). However, passing a null variable indeed equals to null, so that object v = null; Convert.ToString(v) == string.Empty returns true (see this answer).Unpaidfor
@HeyJude - well spotted, thank you! I'll update accordingly.Touzle
G
14

It is because MessageBox.Show() is implemented with pinvoke, it calls the native Windows MessageBox() function. Which doesn't mind getting a NULL for the lpText argument. The C# language has much stricter rules for pure .NET instance methods (like ToString), it always emits code to verify that the object isn't null. There's some background info on that in this blog post.

Groschen answered 25/1, 2011 at 12:52 Comment(0)
T
7

Behind the scenes concat is being called in your follow up question / update E.g

string snull = null;

string msg = "hello" + snull;

// is equivalent to the line below and concat handles the null string for you.
string msg = String.Concat("hello", snull);

// second example fails because of the toString on the null object
string msg = String.Concat("hello", snull.ToString());

//String.Format, String.Convert, String.Concat all handle null objects nicely.
Triangular answered 18/4, 2012 at 10:37 Comment(4)
Can you show us this behind the scenes because I surely can't find it in mscorlib...Overtop
So you mean String utility methods just convert it to 'null' string if value returned is null ?Kurdistan
@RobertKoritnik Use ildasm.exe on compiled sample code, and you will see what James wrote.Expertism
I'm sorry but, this is gold when you have nullable integers. You can write string s = "" + myInt; Thanks, 6 years later !Bustee
S
3

You are trying to execute the ToString() method on a null. You need a valid object in order to execute a method.

Sparoid answered 25/1, 2011 at 12:41 Comment(0)
R
1

The .show function must have null checking and handle it.

Referendum answered 25/1, 2011 at 12:41 Comment(2)
As others have said, the exception is raised because a method is called on a null reference.Horta
Indeed. That is the obvious part.Referendum
G
1

ToString() can't operate on null reference of s vairable

The shortest way

obj?.ToString() 

Another correct ways

obj?.ToString() ?? string.Empty  
obj?.ToString() ?? "default string value"  

https://www.informit.com/articles/article.aspx?p=2421572

Gel answered 22/9, 2022 at 10:16 Comment(0)
L
0

Because, the second call is expecting an object of "s" to satisfy a ToString() method request. so, before .Show() is called, the s.ToString() would failed with an attempt to call a method.

Interestingly, While .Show() is implemented correctly, many such methods expect non null instances to be passed in. Usually, that is when you use a NullObject pattern so that the caller should not have to deal with this kind of behavior.

Lidless answered 25/1, 2011 at 12:44 Comment(0)
P
0

Probably the Show method handles a null value and just shows nothing. The second use of s - s.ToString() fails because you there is no ToString method to run.

Powe answered 25/1, 2011 at 12:46 Comment(0)
T
0

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.'

enter image description here

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

enter image description here

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

}
Turning answered 17/4, 2023 at 14:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.