Why should I explicitly surround with “unchecked”?

后端 未结 3 1984
余生分开走
余生分开走 2021-01-17 14:40

Is there anyone able to explain me this strange behavior?

    int i = 0x1234;
    byte b1 = (byte)i;
    byte b2 = (byte)0x1234;         //error: const value         


        
相关标签:
3条回答
  • 2021-01-17 15:07

    You're tripping over a part of section 7.19 of the C# 4 spec:

    Unless a constant expression is explicitly placed in an unchecked context, overflows that occur in integral-type arithmetic operations and conversions during the compile-time evaluation of the expression always cause compile-time errors.

    Basically, the point is that even if you're happy to allow operations to overflow at execution time, if you're trying to use a constant expression which can't be converted to the target type at compile time, you have to tell the compiler that you really know what you're doing.

    For example, in this case you're losing information - it'll be equivalent to

    byte b3 = 0x34;
    

    so you'd normally be better off just specifying that, to give you clearer code which doesn't mislead the reader. It's relatively rare that you want to overflow in a constant - most of the time you should just specify the valid value instead.

    0 讨论(0)
  • 2021-01-17 15:10

    You shouldn't surround this with unchecked. Unchecked allows assignment of dangerous value types to a type, which may cause overflows.

    byte b1 = (byte)i; will cause an overflow or cast exception at runtime.

    byte b2 = (byte)0x1234; is invalid because you can't store values larger than 0xFF in a byte.

    byte b3 = unchecked((byte)0x1234); will place either 0x34 or 0x12 (depending on the CLR implementation) into b3, and the other byte will overflow.

    byte b4 = checked((byte)i); is the same as byte b1 = (byte)i;

    byte b5 = (byte)(int)0x1234; will cast 0x1234 to an int, and then try to cast it to byte. Again, you can't convert 0x1234 to a byte because it's too large.

    0 讨论(0)
  • 2021-01-17 15:11

    This is not a strange behaviour, the valid range for a variable of the byte data type is 0-255 but when you convert HEX 0x1234 value into decimal system you got 4660. So unchecked used to control the overflow-checking integral-type arithmetic operations and conversions.

    You can find that unchecked often used in GetHashCode() implementation which does numeric operations to calculate the final hash code.

    To summarize you should use unchecked when the final result value of integer-type operations is not matter but overflow could happen.

    0 讨论(0)
提交回复
热议问题