6

Is there a reason why I can't use the following code?

ulong test(int a, int b)
{
    return a == b ? 0 : 1;
}

It shows me:

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

The following will work:

ulong test(int a, int b)
{
    return false ? 0 : 1;
}

I know how to solve the problem. I just want to know the reason.

Thanks.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • In the final code block, does it work if you replace `false` with `true`? Maybe there's some reason that `1` can be implicitly converted by `0` can't? – Dan Forbes Sep 30 '15 at 16:51
  • Already tested, it makes no difference. – Marcel Niehüsener Sep 30 '15 at 16:52
  • 6
    That `false ? 0 : 1` is constant expression. That `return a == b ? 0 : 1` is not. Constant expression of type `int` allowed be converted implicitly to `ulong` if it fit in `ulong` range. – user4003407 Sep 30 '15 at 16:52
  • 1
    The reason i think because compiler evaluates the expression so there is no error for second one. it will be compiled as `return 1` – M.kazem Akhgary Sep 30 '15 at 16:53
  • 1
    "I just want to know the reason." Because that would add complexity to the compiler for no good reason. – Roger Lipscombe Sep 30 '15 at 17:09

3 Answers3

4

Let's take a look at the resulting IL code of the second method:

IL_0000:  nop
IL_0001:  ldc.i4.1
IL_0002:  conv.i8
IL_0003:  stloc.0
IL_0004:  br.s       IL_0006
IL_0006:  ldloc.0
IL_0007:  ret

At IL_0001 the literal 1 is pushed onto the stack (so the expression return false ? 0 : 1; is evaluated at compile-time and embedded into IL as a constant) and at IL_0002 this literal is converted into an Int64.

From MSDN:

A constant-expression (Section 7.15) 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.

Since 1 is in the range of the ulong data type, such conversion will always succeed. The compiler knows that and therefore performs an implicit conversion.

Kapol
  • 6,383
  • 3
  • 21
  • 46
2

Variables typed as int cannot be implicitly converted to ulong, because an int can represent a negative value, while a ulong cannot. A constant can be implicitly converted, provided that the value of the constant expression is non-negative.

Your second example is a constant expression.

phoog
  • 42,068
  • 6
  • 79
  • 117
0

This will work:

ulong test(int a, int b)
{
    return a == b ? 0UL : 1UL;
}

See, the compiler infers the type from the size of the number, so if you want a specific type, you have to give the suffix. See the Literals section on this MSDN page

Edit: As pointed out to me, this question was not looking for an answer on how to make it work. I believe there is still some value in the MSDN article linked. It provides information that can explain why the failing case is not working, but not as to why the other passes. Interesting problem indeed.

David Watts
  • 2,249
  • 22
  • 33
  • 2
    The question isn't about how to make it work, it's asking why the second case works when the first does not. – juharr Sep 30 '15 at 16:53
  • @juharr So it is. Getting to the end of the day and my brain is fried here. Although the literals part still applies right? It explains why it doesn't work, but not why the second case does though. – David Watts Sep 30 '15 at 16:54