Я провел некоторое исследование по этому поводу, используя разные методы для присвоения значений обнуляемому int. Вот что произошло, когда я делал разные вещи. Следует прояснить, что происходит. Имейте в виду: Nullable<something>
или сокращенное обозначение something?
- это структура, для которой компилятор, похоже, проделывает большую работу, чтобы позволить нам использовать значение null, как если бы это был класс.
Как вы увидите ниже, SomeNullable == null
и SomeNullable.HasValue
всегда будет возвращать ожидаемое значение true или false. Хотя это не показано ниже, SomeNullable == 3
также действителен (при условии, что SomeNullable - это int?
).
Хотя SomeNullable.Value
выдает нам ошибку времени выполнения, если мы присвоили null
SomeNullable
. Фактически, это единственный случай, когда значения NULL могут вызвать у нас проблему из-за комбинации перегруженных операторов, перегруженного метода object.Equals(obj)
, оптимизации компилятора и обезьяньего бизнеса.
Вот описание некоторого кода, который я запускал, и то, что он выводил в метках:
int? val = null;
lbl_Val.Text = val.ToString(); //Produced an empty string.
lbl_ValVal.Text = val.Value.ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValEqNull.Text = (val == null).ToString(); //Produced "True" (without the quotes)
lbl_ValNEqNull.Text = (val != null).ToString(); //Produced "False"
lbl_ValHasVal.Text = val.HasValue.ToString(); //Produced "False"
lbl_NValHasVal.Text = (!(val.HasValue)).ToString(); //Produced "True"
lbl_ValValEqNull.Text = (val.Value == null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValValNEqNull.Text = (val.Value != null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
Хорошо, попробуем следующий метод инициализации:
int? val = new int?();
lbl_Val.Text = val.ToString(); //Produced an empty string.
lbl_ValVal.Text = val.Value.ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValEqNull.Text = (val == null).ToString(); //Produced "True" (without the quotes)
lbl_ValNEqNull.Text = (val != null).ToString(); //Produced "False"
lbl_ValHasVal.Text = val.HasValue.ToString(); //Produced "False"
lbl_NValHasVal.Text = (!(val.HasValue)).ToString(); //Produced "True"
lbl_ValValEqNull.Text = (val.Value == null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValValNEqNull.Text = (val.Value != null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
Все так же, как и раньше. Имейте в виду, что инициализация с помощью int? val = new int?(null);
с передачей null конструктору привела бы к ошибке времени COMPILE, поскольку значение VALUE объекта, допускающего значение NULL, НЕ допускает значения NULL. Только сам объект-оболочка может иметь значение null.
Точно так же мы получим ошибку времени компиляции из:
int? val = new int?();
val.Value = null;
не говоря уже о том, что val.Value
в любом случае является свойством только для чтения, что означает, что мы даже не можем использовать что-то вроде:
val.Value = 3;
но опять же, полиморфные перегруженные операторы неявного преобразования позволяют нам:
val = 3;
Не нужно беспокоиться о полисом, что такое, если оно работает правильно? :)
person
Perrin Larson
schedule
11.04.2014
HasValue
, поскольку считаю, что слова более читабельны, чем символы. Однако все зависит от вас и от того, что подходит вашему стилю. - person Jake Petroules   schedule 31.05.2010.HasValue
имеет больше смысла, поскольку обозначает, что тип имеет типT?
, а не тип, который может допускать значение NULL, например строки. - person user3791372   schedule 11.06.2016