空字符串上的 ToString

发布于 2024-10-13 15:34:34 字数 359 浏览 2 评论 0原文

为什么其中第二个会产生异常,而第一个却不会?

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

更新 - 我可以理解的异常,(对我来说)令人困惑的是为什么第一部分没有显示异常。这与消息框无关,如下所示。

例如:

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

第一部分似乎隐式地将 null 转换为空白字符串。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

沫离伤花 2024-10-20 15:34:34

因为您无法在 null 引用上调用实例方法 ToString()

MessageBox.Show() 可能是为了忽略 null 并打印出空消息框而实现的。

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.

寂寞笑我太脆弱 2024-10-20 15:34:34

由于这个问题在 Google 上搜索“c# toString null”时排名相当高,因此我想补充一点,Convert.ToString(null) 方法将返回一个空空字符串,消息框会忽略该字符串。

但是,为了重申其他答案,您可以在此示例中使用 string.Concat("string", null)

编辑 - 根据下面 HeyJude 的评论修改答案。正如所指出的,像 Convert.ToString(null).Length 这样的方法将引发异常。

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.

箹锭⒈辈孓 2024-10-20 15:34:34

这是因为MessageBox.Show()是用pinvoke实现的,它调用了原生的Windows MessageBox()函数。这并不介意 lpText 参数为 NULL。 C# 语言对纯 .NET 实例方法(如 ToString)有更严格的规则,它总是发出代码来验证对象不为 null。此 博客文章

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.

帅冕 2024-10-20 15:34:34

在您的后续问题/更新中调用幕后 concat 例如

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.

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.
爱冒险 2024-10-20 15:34:34

您正在尝试对 null 执行 ToString() 方法。您需要一个有效的对象才能执行方法。

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

安静被遗忘 2024-10-20 15:34:34

.show 函数必须进行 null 检查并处理它。

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

故事和酒 2024-10-20 15:34:34

ToString() 不能对 s vairable 的空引用进行操作

最短的方法

obj?.ToString() 

另一种正确的方法

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

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

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

寂寞美少年 2024-10-20 15:34:34

因为,第二次调用期望“s”对象满足 ToString() 方法请求。因此,在调用 .Show() 之前,s.ToString() 会因尝试调用方法而失败。

有趣的是,虽然 .Show() 正确实现,但许多此类方法期望传入非空实例。通常,这是当您使用 NullObject 模式,以便调用者不必处理这种行为。

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.

对你再特殊 2024-10-20 15:34:34

可能 Show 方法处理空值并且什么也不显示。
s - s.ToString() 的第二次使用失败,因为没有要运行的 ToString 方法。

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.

愿与i 2024-10-20 15:34:34

正如您自己所说,它与 MessageBox 无关,它取决于 ToString() 方法的实现。

例如查看 struct Nullable其中 T : struct 来自 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 partial struct Nullable<T> where T : struct

对于 .NET 7,它的 ToString() 实现如下所示:

public override string? ToString() => hasValue ? value.ToString() : "";

因此即使在 tc.TestEnum< 的 null 对象上调用 ToString(),以下代码也会在 MessageBox.Show(s.ToString()); 上出现异常/代码>。

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: '对象引用未设置为
对象的实例。'

输入图片这里的描述

System.Runtime查看class String

[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

这里我们有另一个实现,它将抛出您看到的错误:

// Returns this string.
public override string ToString()
{
    return this;
}

但是从开始新项目默认启用 .NET 6< enable

https://learn.microsoft.com/en-us/dotnet/ csharp/nullable-references

因此上面的代码会给你两个警告:

string s = null; -> CS8600 将 null 文字或可能的 null 值转换为不可为 null 的类型。

MessageBox.Show(s.ToString() ); -> CS8602 取消引用可能为空的引用

在此处输入图像描述

像这样重写代码,错误就会消失:

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

}

或者简单地使用 null 条件运算符 ?. 就像 @mr R 写道:

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

}

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

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文