Почему.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(), но выполняет другую задачу.