Почему.ToString() для пустой строки вызывает нулевую ошибку, когда.ToString() работает нормально для обнуляемого int с нулевым значением?

selectedItem имеет два поля:

  • int? _cost
  • string _serialNumber

В этом примере _cost а также _serialNumber из selectedItem ОБА НУЛЬ. Я читаю через поля selectedItem через их свойства и заполняя текстовые поля их значениями, когда...

TextBox1.Text = selectedItem.Cost.ToString(); //no error
TextBox2.Text = selectedItem.SerialNumber.ToString(); //error

Я это понимаю SerialNumber.ToString() является избыточным (потому что это уже строка), но я не понимаю, почему это вызывает это исключение:

Обнуляемый объект должен иметь значение.

  • int? _cost обнуляется, и не имеет значения, но это не дает мне исключения.
  • string _serialNumber имеет значение nullable и не имеет значения, но все же дает мне исключение.

Этот вопрос затрагивает этот вопрос, парень, по сути, задает то же самое, но нет определенного ответа, и он также не объясняет, почему обнуляемый int? Например, могу ли я использовать .ToString() в обнуляемом int, но не в пустой строке?

8 ответов

Решение

Так как string типа по null на самом деле ничего не указывает, в памяти нет объектов.
Но int? тип (обнуляемый) даже со значением, установленным в null все еще указывает на какой-то объект.
Если вы прочтете "CLR через C#" Джеффри Рихтера, вы обнаружите, что обнуляемые типы - это просто классы фасадов для общих типов с некоторыми инкапсулированными логиками, чтобы сделать работу с БД нулевой более удобной.

Проверьте msdn, чтобы узнать о обнуляемых типах.

Nullable<int> это struct и не может быть нулевым. Таким образом, вызов метода для "нулевой" структуры все еще работает.

Существует некоторая "магия компилятора", которая делает _cost == null правильное выражение.

int? на самом деле не является объектом, но это Nullable<int> объект.

Поэтому, когда вы объявляете int? _Costвы на самом деле объявляете Nullable<int> _Cost и собственность _Cost.Value является undefined не _Cost сам объект

Это на самом деле синтаксический сахар для использования non nullable типы как int, bool или же decimal без труда.

По данным MSDN:

Синтаксис T? это сокращение для System.Nullable<T>, где T это тип значения Две формы взаимозаменяемы.

Nullable на самом деле является структурой, предоставляющей два свойства: HasValue и Value. Если вы сделаете это, вы получите свою ошибку:

int? i = null;
i.Value.ToString()

Для того чтобы проверить, есть ли у вас int? имеет значение, к которому вы можете получить доступ i.HasValue

Строка является ссылочным типом, но обнуляемое int является типом значения. Вот хорошее обсуждение различий http://www.albahari.com/valuevsreftypes.aspx.

Причина проста. int? или же Nullable<int> является структурой или типом значения, оно никогда не может быть нулевым.

Итак, что происходит, когда мы делаем:

int? _cost = null;

_cost будет иметь два поля Value а также HasValue когда мы назначаем null в _cost его HasValue флаг будет установлен в false и Value поле будет назначено default(T) в случае int? было бы 0,

Теперь, когда мы звоним ToString на _cost, Nullable<T> имеет определение переопределения ToString, который, если мы посмотрим на предоставленную Microsoft ссылку на источник, реализован следующим образом:

public override string ToString() {
    return HasValue ? value.ToString() : "";
}

Таким образом, он возвращает пустую строку, так как _cost назначен null,

Теперь приходит случай string _serialNumber, бытие string это ссылочный тип, и он может содержать чисто null, Если он держит null потом звоню ToString на нем будет получено Null Reference Exception, как и ожидалось.

Вы можете увидеть: Типы значений и Типы ссылок - MSDN

Я думаю, что причина в том, что когда компилятор встречает примитивный тип данных, он переносит его в соответствующий объект. Вызов метода toString() - это просто косвенный вызов (перенос и вызов метода), и там обрабатывается исключение. В случае с String мы напрямую вызываем метод. При указании на ноль метод выдает исключение.

TextBox2.Text = selectedItem.SerialNumber.ToString(); //error

выдает ошибку, потому что она вызывает функцию ToString(), которая является членом System.String. Эта функция возвращает этот экземпляр System.String; фактическое преобразование не выполняется. Кроме того, String является ссылочным типом. Ссылочный тип содержит указатель на другую область памяти, в которой хранятся данные.

TextBox1.Text = selectedItem.Cost.ToString(); //no error

не дает ошибки, потому что вызывает функцию ToString(), которая является членом System.Integer. Эта функция преобразует числовое значение этого экземпляра в его эквивалентное строковое представление. Кроме того, Integer является типом значения. Тип данных является типом значения, если он хранит данные в своем собственном распределении памяти.

То же имя функции ToString(), но выполняет другую задачу.

Метод String.ToString

Метод Int32.ToString

Типы значений и ссылочные типы

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