Я провів деякі дослідження з цього приводу різних методів, щоб присвоїти значення нульовому 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;
Не потрібно турбуватися про те, що багато чого може бути, але поки це працює правильно? :)