Я провів деякі дослідження з цього приводу різних методів, щоб присвоїти значення нульовому int. Ось що сталося, коли я робив різні речі. Слід уточнити, що відбувається. Майте на увазі: Nullable<something>або скорочення something?- це структура, над якою компілятор, здається, робить багато роботи, щоб ми могли використовувати з null так, як якщо б це був клас.
Як ви побачите нижче, SomeNullable == nullі SomeNullable.HasValueзавжди буде повертати очікувану правду чи хибність. Хоча це не продемонстровано нижче, SomeNullable == 3він також дійсний (якщо припустити, що SomeNullable є int?).
У той час як SomeNullable.Valueотримує нам повідомлення про помилку виконання , якщо ми призначили nullна SomeNullable. Насправді це єдиний випадок, коли зведені нанівець проблеми можуть створити нам проблему, завдяки комбінації перевантажених операторів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);нулем, переданим конструктору, спричинила б помилку в часі КОМПЛІЄТНО, оскільки ЗНАЧЕННЯ ЗНАЧЕННЯ об'єкта НЕ зводиться до нуля. Тільки сам об’єкт обгортки може дорівнювати нулю.
Так само ми отримаємо помилку часу компіляції з:
int? val = new int?();
val.Value = null;
не кажучи вже про те, що val.Valueце властивість лише для читання, тобто ми навіть не можемо використовувати щось на зразок:
val.Value = 3;
але знову ж таки, поліморфні перевантажені оператори неявного перетворення дозволяють нам робити:
val = 3;
Не потрібно турбуватися про те, що багато чого може бути, але поки це працює правильно? :)