Тип умовного вираження неможливо визначити, оскільки немає неявного перетворення між 'int' та <null>


167

Чому це не складається?

int? number = true ? 5 : null;

Тип умовного вираження неможливо визначити, оскільки немає неявного перетворення між 'int' та <null>


Відповіді:


341

Специфікації (§7.14) говорять , що для умовного виразу b ? x : y, є три можливості, або xі yобидва мають типу і певні умови , хороші виконані, тільки один з xі yмають тип , і певні умови , хороші будуть виконані, або під час компіляції помилки трапляється. Тут "певні хороші умови" означають можливі певні перетворення, про які ми детально опишемося нижче.

Тепер перейдемо до германської частини специфікації:

Якщо тільки один з xі yмає тип, і обидва, xі yнеявно перетворюються на цей тип, то це тип умовного виразу.

Проблема тут полягає в тому, що в

int? number = true ? 5 : null;

лише один із умовних результатів має тип. Ось xце intбуквально, і yце nullяка не НЕ мають типу і nullНЕ неявно розкладається в int1 . Тому "певні хороші умови" не виконуються, і виникає помилка часу компіляції.

Там є два шляхи навколо цього:

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 : Зауважте далі, що тип лівої частини ігнорується при визначенні типу умовного виразу, що тут є загальним джерелом плутанини.


4
Добре цитуючи специфікацію, щоб проілюструвати, чому це відбувається - +1!
JerKimball

8
Інший варіант є new int?()замість (int?)null.
Гуванте

1
Це також випадок , якщо у вас є обнуляє типу поля бази даних, наприклад, обнуляється DateTime і ви намагаєтеся і гіпсові Дані DateTime, коли він Infact потрібно(DateTime?)
Майк Upjohn

73

null не має жодного ідентифікуючого типу - для його задоволення просто потрібно трохи підтягнути:

int? number = true ? 5 : (int?)null;

3
Або можете зробитиint? number = true ? 5 : null as int?;
Бред М

Приємна відповідь, що прибиває крапку. Приємне читання: ericlippert.com/2013/05/30/what-the-meaning-of-is-is
Бенджамін

Справа не в тому, що nullвін не має ідентифікованого типу. Проблема полягає в тому, що немає неявного перетворення з nullна int. Деталі тут .
Jason

цікаво, що int? number = true ? 5 : (int?)null;і int? number = true ? (int?)5 : null;обидва складають !! Скретч, подряпин
davidhq

2
Я висвітлюю саме те , чому це відбувається у моїй відповіді .
Jason

4

Як уже згадували інші, 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>.


1

У 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;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.