Обнуляемый ToString ()

143

Я везде вижу конструкции типа:

int? myVar = null;
string test = myVar.HasValue ? myVar.Value.ToString() : string.Empty;

Почему бы просто не использовать:

string test = myVar.ToString();

Разве это не то же самое? По крайней мере, Reflector говорит, что:

public override string ToString()
{
  if (!this.HasValue)
  {
    return "";
  }
  return this.value.ToString();
}

Итак, это правильно (более короткая версия) или мне что-то не хватает?

IamDeveloper
источник
1
Я не видел такого кода :)
tymtam 01

Ответы:

113

Вы совершенно правы. Также в этом вопросе предлагается первое решение, хотя на самом деле никто не замечает, что он ToString()уже дает правильный ответ.

Может быть аргументом для более развернутого решения является читаемость: Когда вы вызываете ToString()на то , что предполагается , что nullвы обычно ожидаетеNullReferenceException , хотя здесь он не брошен.

Томас Вана
источник
21
На самом деле это заметили как минимум два человека: Эрик Липперт и Йоханнес Рассел.
Джон Скит,
8
Хотя я уверен, что вы имели в виду не это, на самом деле ссылка здесь не пустая. Nullable <T> - это тип значения. Вот почему вызов ToString()работает без NullReferenceExceptionброска.
Thorarin
3
Если бы это был менталитет, вы все .HasValueравно ожидали бы выбросить это исключение.
Extragorey
Другая причина, по которой люди используют подробную версию, может заключаться в паритете с выражениями, например, myNullableDateTime.HasValue ? myNullableDateTime.Value.ToString("d") : nullгде вам нужен развернутый объект для доступа к желаемому ToStringметоду. Конечно, для этого есть более лаконичное решение:$"{myNullableDateTime:d}"
Extragorey
14

Я думаю, что у многих есть такие проверки, потому что это неестественное поведение объекта, который может содержать нулевое значение.

Андрей Беззуб
источник
@Andrew, согласен, потому что люди (вроде меня) сначала думают, что это вызовет исключение.
Натан Куп,
1
Я понятия не имел, что такое поведение. Я определенно подумал бы, что любая конструкция, которая возвращает true для (x == null), также вызовет исключение NullReferenceException, если вы вызовете x.ToString ().
Дэн Брайант
5

Нет, вы правы, более короткая версия совпадает с тем, что сделали другие люди в этом отношении. Другой конструкцией, которую я часто использую вместо тернарной с значениями NULL, является оператор объединения NULL. который также защищает вас от нулей. Для ToString () это не обязательно (как вы указали), но для значений int по умолчанию (например) он работает хорошо, например:

int page = currentPage ?? 1;

который позволяет вам выполнять все целочисленные операции на странице без первой явной проверки на null и вызова значения в currentPage (где currentPage - это int? возможно, передается как параметр)

Павел
источник
5

Я знаю, спустя долгое время это стало актуальным, но ... Я подозреваю, что это потому, что для типов, допускающих значение NULL, таких как int? метод .ToString () не позволяет использовать строки формата. См. Раздел Как отформатировать объект DateTime, допускающий значение NULL, с помощью ToString ()? . Возможно, в исходном коде в .ToString () была строка формата, или, возможно, кодировщик забыл, что .ToString () без строки формата все еще доступен для типов, допускающих значение NULL.

Outis nihil
источник
3

может быть это просто следование шаблону? или они не знают серверную часть. вы правы код точно такой же. вы даже можете:

int? i = null;
i.ToString(); //No NullReferenceException
Андрей
источник
Возможно, вам придется пойти по длинному пути, если ToString () должен иметь инвариантный язык и региональные параметры, так как значения NULL не имеют его в своем меню.
Ε Г И І И О
1

int?это синтаксический сахар, который упрощает объявление переменной, допускающей значение NULL. Это то же самое, что и Nullable<int>.

Итак, если вы посмотрите на реализацию ToString()метода для Nullable<T> (см. Ниже) , вы можете заметить, что он возвращает пустую строку, если она не имеет значения.

public struct Nullable<T> where T : struct
{
    public override string ToString()
    {
      if (!this.hasValue)
        return "";
      return this.value.ToString();
    }
}

Что говорит MSDN:

Nullable.ToString - метод

Возвращает текстовое представление значения текущего объекта, допускающего значение NULL, если свойство HasValue имеет значение true, или пустую строку («»), если свойство HasValue имеет значение false.

Таким образом, следующий код будет выводить на консоль пустую строку вместо того, чтобы генерировать ArgumentNullExceptionисключение.

static void Main(string[] args)
{
    int? a = null;
    Console.WriteLine(a.ToString()); // Prints empty string to console.
}
Алексей Манюк
источник