Why does ?: cause a conversion error while if-else does not?

C#.NetType Conversion

C# Problem Overview


Making some changes in the code I use the next line:

uint a = b == c ? 0 : 1;

Visual Studio shows me this error:

> Cannot implicitly convert type 'int' to 'uint'. An explicit conversion exists (are you missing a cast?)

But if I use the code:

uint a; 

if (b == c) 
    a = 0; 
else 
    a = 1;

It works correctly without any error or warning. Why?

C# Solutions


Solution 1 - C#

> Why can't I use uint a = b == c ? 0 : 1;?

The type of the expression b == c ? 0 : 1 is int. As shown in this table, there is no implicit conversion from int to uint, so this is not allowed.

> Why can I use a = 0?

Because there is special treatment of numeric types when the value is a constant expression.

From section 6.1.9 of the C# specification:

>- A constant expression of type int can be converted to type sbyte, byte, short, ushort, uint, or ulong, provided the value of the constant-expression is within the range of the destination type. > >- A constant expression of type long can be converted to type ulong, provided the value of the constant expression is not negative.

As indicated in the first bullet a = 0 and a = 1 are both allowed because 0 and 1 are constant expressions and are valid uint values. Basically what this boils down to is that the compiler can easily determine at compile time that these conversions are valid, so it allows them.

Incidentally, if the b == c part of your first example were changed to a constant expression (e.g. true), then the whole conditional operator expression would be a constant expression and the code would compile.

Solution 2 - C#

If b==c were a constant expression then the whole conditional operator would be considered a constant expression and so, then, the rule allowing constant expressions of type int to be converted to other int types would apply and it would compile.

Obviously, b==c is not a constant expression and so the result of the conditional operator cannot be known until runtime and so the exemption that allows an implicit conversion of ints to uint (for constant expressions) does not apply.

In your if/else variant, both of the actual assignments are constant expressions.

Solution 3 - C#

You should use literals to make your code work correctly like this:

uint a = b == c ? 0U : 1U;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRuben AguilarView Question on Stackoverflow
Solution 1 - C#JLRisheView Answer on Stackoverflow
Solution 2 - C#Damien_The_UnbelieverView Answer on Stackoverflow
Solution 3 - C#teo van kotView Answer on Stackoverflow