Conditional type of operator return with literal digits

?: Operator (C # link)

Any type of expression first_expression and second_expression must be the same, or an implicit conversion must exist from one type to another.

Integer literals

If a literal does not have a suffix, it has the first of these types in which its value can be represented: int, uint, long, ulong.

Consider:

var value = test ? (Int64)1 : 0; 

0, decimal digital literal without suffix will be converted to int . int can be implicitly converted to Int64 . Since this conversion takes place in only one direction, we can feel safe that the return value will be Int64.

But:

 var value = test ? (UInt64)1 : 0; 

UInt64 and int cannot be implicitly converted to each other, but this code is compiled and run, and the resulting type is UInt64 .

At what point is type 0 determined?

If two types are implicitly hidden with each other, then which of the two types will you find yourself in? (I do not think this is going well, but classes created by the user can implement such casting.)

Previous research:
I found several other questions with similar headings, but they were all related to null or null types.

Relevance: It matters in my code, because we immediately pass this result to ByteWriter.Write and want to get the correct overload, which writes the correct number of bytes. The examples, of course, are greatly simplified.

Alternative syntax makes the result explicit may be the best option for clarity, regardless of what actually happens without an explicit cast:

 var value = test ? (UInt64)1 : (UInt64)0; 
+4
source share
2 answers

Remember that there is one set of implicit conversions between integer types when compilation time constant numbers (literals) and another set of transforms if they are not constants.

Your interesting example:

 var value = test ? (UInt64)1 : 0; 

which can also be written:

 var value = test ? 1ul : 0; 

where the suffix ul means ulong , i.e. System.UInt64 .

When literals (constants) are used, there is an implicit conversion from int ( System.Int32 ) to ulong , but only when this int constant is non-negative. This is really the same as:

 const ulong a = 1ul; const int b = 0; var value = test ? a : b; // also works fine 

It works, as I said, due to an implicit constant conversion from int (since the compiler knows that b not negative) to ulong .

Now take const to get:

 ulong a = 1ul; int b = 0; var value = test ? a : b; // compile-time error, no implicit conversion in either direction! 

We see that with non-constants there is no implicit conversion in either direction, therefore there is no better general type for a and b , and this fails.

+3
source

True, a generic int cannot be implicitly converted to a UInt any length. But here we are not talking about a common, unknown int . We say 0 , which can be converted (even at compile time, which I suspect is a compiler), to UInt .

I suggest you use the int parameter (or another value that the compiler cannot infer from the analysis of the data stream) and see what happens.

+1
source

Source: https://habr.com/ru/post/1499483/


All Articles