Error when trying to perform a bitwise not (~) on a UInt16 in C#

后端 未结 3 1840
醉酒成梦
醉酒成梦 2021-01-26 05:52

For some reason, I am simply not understanding (or seeing) why this works:

UInt32 a = 0x000000FF;
a &= ~(UInt32)0x00000001;

but this does n

3条回答
  •  慢半拍i
    慢半拍i (楼主)
    2021-01-26 05:58

    Because §14.6.4 of the Standard (ISO 23270) says:

    14.6.4 Bitwise complement operator

    For an operation of the form ~x, unary operator overload resolution (§14.2.3) is applied to select a specific operator implementation. The operand is converted to the parameter type of the selected operator, and the type of the result is the return type of the operator. The predefined bitwise complement operators are:

    int operator ~(int x);
    uint operator ~(uint x);
    long operator ~(long x);
    ulong operator ~(ulong x);
    

    For each of these operators, the result of the operation is the bitwise complement of x.

    If you work through the unary operator overload resolution specified in §14.2.3, you'll find that, as noted by §14.2.6.1 ("Unary numeric promotions"), which is informative rather than normative, that the net effect is this:

    Unary numeric promotion occurs for the operands of the predefined +, , and ~ unary operators. Unary numeric promotion simply consists of converting operands of type sbyte, byte, short, ushort, or char to type int.

    So despite your cast, ~(ushort)0x0001, the compiler is smart enough to note the constant expression and do constant folding, meaning that the end result is a signed 32-bit integer with a value of -2, or 0xFFFFFFFE. And...

    Since the expression, a &= b ; is exactly equivalent to a = a & b ;, you are trying to do a bitwise AND of a ushort and an int. The ushort is upcast to an int and the bitwise AND evaluated, yielding a signed 32-bit integer result. . . . which can't be assigned to a ushort (unsigned 16-bit).

    That is why.

提交回复
热议问题