Чому це не складається?
int? number = true ? 5 : null;
Тип умовного вираження неможливо визначити, оскільки немає неявного перетворення між 'int' та <null>
Чому це не складається?
int? number = true ? 5 : null;
Тип умовного вираження неможливо визначити, оскільки немає неявного перетворення між 'int' та <null>
Відповіді:
Специфікації (§7.14) говорять , що для умовного виразу b ? x : y
, є три можливості, або x
і y
обидва мають типу і певні умови , хороші виконані, тільки один з x
і y
мають тип , і певні умови , хороші будуть виконані, або під час компіляції помилки трапляється. Тут "певні хороші умови" означають можливі певні перетворення, про які ми детально опишемося нижче.
Тепер перейдемо до германської частини специфікації:
Якщо тільки один з
x
іy
має тип, і обидва,x
іy
неявно перетворюються на цей тип, то це тип умовного виразу.
Проблема тут полягає в тому, що в
int? number = true ? 5 : null;
лише один із умовних результатів має тип. Ось x
це int
буквально, і y
це null
яка не НЕ мають типу і null
НЕ неявно розкладається в int
1 . Тому "певні хороші умови" не виконуються, і виникає помилка часу компіляції.
Там є два шляхи навколо цього:
int? number = true ? (int?)5 : null;
Тут ми всі ще в тому випадку , коли тільки один з x
і y
має тип. Зверніть увагу , що до null
сих пір не має типу поки компілятор не матиме жодних проблем з цим , тому що (int?)5
і null
обидва неявно перетворені в int?
(§6.1.4 і §6.1.5).
Інший спосіб очевидно:
int? number = true ? 5 : (int?)null;
але тепер ми повинні прочитати інший пункт у специфікації, щоб зрозуміти, чому це нормально:
Якщо
x
має типX
іy
має тип,Y
то
Якщо неявне перетворення (§6.1) існує з
X
доY
, але не відY
доX
, тоY
є тип умовного виразу.Якщо неявне перетворення (§6.1) існує з
Y
доX
, але не відX
доY
, тоX
є тип умовного виразу.В іншому випадку не можна визначити тип виразу, і виникає помилка часу компіляції.
Тут x
є тип int
і y
є тип int?
. Немає неявної конверсії з int?
в int
, але є неявна конверсія з int
у int?
такий тип виразу int?
.
1 : Зауважте далі, що тип лівої частини ігнорується при визначенні типу умовного виразу, що тут є загальним джерелом плутанини.
new int?()
замість (int?)null
.
DateTime
, коли він Infact потрібно(DateTime?)
null
не має жодного ідентифікуючого типу - для його задоволення просто потрібно трохи підтягнути:
int? number = true ? 5 : (int?)null;
int? number = true ? 5 : null as int?;
int? number = true ? 5 : (int?)null;
і int? number = true ? (int?)5 : null;
обидва складають !! Скретч, подряпин
Як уже згадували інші, 5 є an int
, і null
не може бути неявно перетворений в int
.
Ось інші способи вирішити проблему:
int? num = true ? 5 : default(int?);
int? num = true ? 5 : new int?();
int? num = true ? 5 : null as int?;
int? num = true ? 5 : (int?)null;
int? num = true ? (int?)5 : null;
int? num = true ? 5 as int? : null;
int? num = true ? new int?(5) : null;
Крім того, де б ви не бачились int?
, ви також можете використовувати Nullable<int>
.
У C# 9
цьому зараз дозволений блог
Ціль набрана ?? і?
Іноді умовні ?? і?: вирази не мають очевидного спільного типу між гілками. Сьогодні такі випадки не вдається, але C # 9.0 дозволить їм, якщо є цільовий тип, який обидві гілки перетворюють на:
Person person = student ?? customer; // Shared base type
int? result = b ? 0 : null; // nullable value type
Або ваш приклад:
// Allowed in C# 9.
int? number = true ? 5 : null;