ToString в пустой строке

Почему второй из них создает исключение, а первый нет?

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

Первая часть, по-видимому, неявно преобразует ноль в пустую строку.

10 ответов

Потому что вы не можете вызвать метод экземпляра ToString() на null ссылка.

А также MessageBox.Show() вероятно, реализовано, чтобы игнорировать нуль и распечатать пустое окно сообщения.

Так как этот вопрос занимает в Google довольно высокий уровень по запросу "C# toString null", я хотел бы добавить, что Convert.ToString(null) Метод вернет пустую строку.

Однако, чтобы подтвердить остальные ответы, вы можете использовать string.Concat("string", null) в этом примере.

Это потому, что MessageBox.Show() реализован с помощью pinvoke, он вызывает встроенную функцию Windows MessageBox(). Который не против получить значение NULL для аргумента lpText. Язык C# имеет гораздо более строгие правила для чистых методов экземпляра.NET (например, ToString), он всегда генерирует код, чтобы убедиться, что объект не является нулевым. Об этом есть некоторая справочная информация в этом посте.

За кулисами в последующем вопросе / обновлении вызывается 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.

Вы пытаетесь выполнить метод ToString() с нулевым значением. Вам нужен действительный объект для выполнения метода.

ToString() не может работать с нулевой ссылкой s vairable

Самый короткий путь

      obj?.ToString() 

Другие правильные способы

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

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

Функция.show должна иметь нулевую проверку и обрабатывать ее.

Потому что второй вызов ожидает, что объект "s" удовлетворит запрос метода ToString(). поэтому перед вызовом.Show() s.ToString() завершится с ошибкой при попытке вызвать метод.

Интересно, что хотя.Show() реализован правильно, многие такие методы ожидают передачи ненулевых экземпляров. Обычно это происходит, когда вы используете шаблон NullObject, чтобы вызывающая программа не сталкивалась с подобным поведением.

Вероятно, метод Show обрабатывает нулевое значение и просто ничего не показывает. Второе использование s - s.ToString() завершается неудачно, потому что у вас нет метода ToString для запуска.

Как вы сами говорите, это не имеет ничего общего сMessageBox, это зависит от реализации метода.

Например, глядя наstruct Nullable<T> where T : structиз этого в качестве примера используется перечисление с нулевым значением:

      [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 выглядит следующим образом:

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

Поэтому следующий код дает исключение, хотяToString()вызывается для нулевого объекта для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: «Ссылка на объект не установлена ​​на экземпляр объекта».

Смотря наclass Stringот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

Здесь у нас есть еще одна реализация, которая выдает ошибку, которую вы видите:

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

Однако начиная с.NET 6< <Nullable>enable</Nullable>включен по умолчанию для новых проектов.

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

Таким образом, приведенный выше код выдаст вам два предупреждения:

string s = null;-> CS8600 Преобразование нулевого литерала или возможного нулевого значения в тип, не допускающий значения 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; }

}

Или просто используя оператор с нулевым условием?.как @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; }

}
Другие вопросы по тегам