Незмінний ToString ()


142

Я бачу скрізь такі споруди, як:

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

Чому б не використовувати просто:

string test = myVar.ToString();

Чи не зовсім так? Принаймні рефлектор говорить, що:

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

Отже, це правильно (коротша версія) чи я щось пропускаю?


1
Я ще не бачив такого коду :)
tymtam

Відповіді:


112

Ви цілком правильні. Також в цьому питанні пропонується колишнє рішення, поки ніхто насправді не помічає ToString()правильної відповіді.

Можливо, аргументом для більш детального рішення є читабельність: Коли ви закликаєте ToString()щось, що повинно бути null, ви зазвичай очікуєте " a" NullReferenceException, хоча тут це не кидається.


21
Власне, щонайменше двоє людей помітили: Ерік Ліпперт та Йоханнес Рессель.
Джон Скіт

7
Хоча я впевнений, що це не те, що ви мали на увазі, посилання насправді тут недійсне. Nullable <T> - тип значення. Ось чому дзвінок ToString()працює без жодного NullReferenceExceptionкидання.
Торарін

2
Якби це був менталітет, ви б розраховували .HasValueвсе-таки кинути це виняток.
Екстрагорей

Ще одна причина, по якій люди використовують багатослівну версію, може бути для паритету з виразами, наприклад, myNullableDateTime.HasValue ? myNullableDateTime.Value.ToString("d") : nullде вам потрібен розпакований об'єкт для доступу до потрібного ToStringметоду. Звичайно, для цього теж є більш стисле рішення:$"{myNullableDateTime:d}"
Екстрагорей

14

Я думаю, що у багатьох людей є такі перевірки, оскільки це не природна поведінка об'єкта, яка може мати нульове значення.


@Andrew, погодився, адже люди (як я) спочатку думають, що це викине виняток.
Натан Куп

1
Я не мав уявлення, що це така поведінка. Я, безумовно, подумав би, що будь-яка конструкція, яка повертає true для (x == null), також буде кидати NullReferenceException, якщо ви викликаєте x.ToString ().
Ден Брайант

5

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

int page = currentPage ?? 1;

що дозволяє виконувати всі цілі операції на сторінці без першої явної перевірки нуля і виклику значення в currentPage (де currentPage є цілим? можливо передається як парам)


5

Я знаю, довгий час це було актуально, але ... я підозрюю, що це так для таких змінних типів, як Int? метод .ToString () не дозволяє використовувати рядки формату. Див. Як я можу відформатувати нульовий DateTime за допомогою ToString ()? . Можливо, в оригінальному коді був рядок формату в .ToString (), або, можливо, кодер забув, що .ToString () без рядка формату все ще доступний для змінних типів.


3

може бути, це просто слідувати зразку? або вони не знають бекенда. ви праві код точно такий же. Ви навіть можете зробити:

int? i = null;
i.ToString(); //No NullReferenceException

Можливо, вам знадобиться пройти довгий маршрут, якщо ToString () має бути інваріантною культурою, оскільки нуклеуси не мають його у своєму меню.
Ε Г І І І О

1

int?- синтаксичний цукор, який спрощує оголошення нульової змінної. Це те саме, що 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 метод

Повертає текстове подання значення поточного об'єкта Nullable, якщо властивість HasValue є істинним, або порожній рядок (""), якщо властивість HasValue помилково.

Таким чином, наступний код буде друкувати порожній рядок у консолі, а не викидати ArgumentNullExceptionвиключення.

static void Main(string[] args)
{
    int? a = null;
    Console.WriteLine(a.ToString()); // Prints empty string to console.
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.