1

Another post to track the error Cannot implicitly convert type 'long' to 'int'

public int FindComplement(int num) {
    uint i = 0; 
    uint mask = ~i;

    while((mask&num) != 0) mask <<= 1;
    //return ~mask^num; //<-- error CS0266
    return (int)~mask^num; //<--it works with (int)
}

Sorry for too many questions, I'd like to know why return ~mask^num will cause error like

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

In my environment, return ~mask^num; will cause error, while return (int)~mask^num can work. And it seems there is no long type involved here.

Eric Tsui
  • 1,924
  • 12
  • 21
  • because `^`is a long operator and returns also `long` – hotfix Apr 03 '19 at 11:04
  • Possible duplicate of [C# XOR on two byte variables will not compile without a cast](https://stackoverflow.com/questions/2726920/c-sharp-xor-on-two-byte-variables-will-not-compile-without-a-cast) – GSerg Apr 03 '19 at 11:04
  • @hotfix `^` is not a long operator. – GSerg Apr 03 '19 at 11:05
  • 3
    Relevant quote: *Otherwise, if either operand is of type uint and the other operand is of type sbyte, short, or int, both operands are converted to type long.* – GSerg Apr 03 '19 at 11:05
  • @hotfix `long.operator^` is indeed a long operator. E.g. `int.operator^` is not. – GSerg Apr 03 '19 at 11:15

2 Answers2

4

You're trying to perform a ^ operation with operands int and uint. There's no such operator, so both operands are converted to long and the long ^(long, long) operator is used.

From the ECMA C# 5 specification, section 12.4.7.1:

Numeric promotion consists of automatically performing certain implicit conversions of the operands of the predefined unary and binary numeric operators. Numeric promotion is not a distinct mechanism, but rather an effect of applying overload resolution to the predefined operators. Numeric promotion specifically does not affect evaluation of user-defined operators, although user-defined operators can be implemented to exhibit similar effects.

And from 12.4.7.3:

Binary numeric promotion occurs for the operands of the predefined +, –, *, /, %, &, |, ^, ==, !=, >, <, >=, and <= binary operators. Binary numeric promotion implicitly converts both operands to a common type which, in case of the non-relational operators, also becomes the result type of the operation. Binary numeric promotion consists of applying the following rules, in the order they appear here:

  • ... (rules that don't apply here)
  • Otherwise, if either operand is of type uint and the other operand is of type sbyte, short, or int, both operands are converted to type long.
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Appreciated for detailed explanation, now I know where `long` type comes. I may need read Specification before I ask the question next time. Thanks again, Jon Skeet :) – Eric Tsui Apr 03 '19 at 11:43
  • Another thing is the code can work well in c++ without `0U` and `(int)` cast. C# seems more strict about types, at least very different, is that right ? – Eric Tsui Apr 03 '19 at 11:47
  • @EricTsui: It's been a long time since I've worked with C, but they're very different languages in a number of ways. – Jon Skeet Apr 03 '19 at 11:50
0

The type uint holds the numbers from 0 to 4,294,967,295. This means that when you use a regular int as the parameter num, you are doing operations on two different types that have two different ranges. Thus in order to not get this error, you can use ints for everything.

TaF
  • 1
  • 1