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"
Функция.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; }
}