开发者

C# Bitwise OR needs casting with byte *sometimes* [duplicate]

This question already has answers here: Left bit shifting 255 (as a byte) (7 answers) OR-ing bytes in C# gives int [duplicate] (3 answers) 开发者_开发百科 Closed 9 years ago.

I found an odd situation in the C# compiler. Why the cast below is required?

using System;

class Program
{
    private const byte BIT_ZERO_SET = 1;
    private const byte BIT_ONE_SET = 2;
    private const byte BIT_TWO_SET = 4;

    static void Main(string[] args)
    {
        byte b = BIT_ZERO_SET | BIT_ONE_SET;
        Console.WriteLine(b);

        //Does not compile, says needs to cast to int.
        //b = b | BIT_TWO_SET;

        //Compiles...ugly
        b = (byte)(b | BIT_TWO_SET);
        Console.WriteLine(b);

        Console.WriteLine("Press enter.");
        Console.ReadLine();    
    }
}

Thanks.


The various answers here are generally correct, but have a bunch of different facts spread out all over the place. The relevant points are:

1) The result of byte | byte is an int, because there is no | operator defined on bytes.

2) Computations involving only integral compile-time constants are treated as "checked" arithmetic; that is, the compiler verifies that the constant result does not overflow, and so on. A pleasant consequence of this fact is that an assignment of a compile-time constant integer to a variable or constant of a smaller type automatically verifies that the constant integer fits into the smaller type. If it does, then the assignment is allowed without an explicit cast. If it does not, then a compile-time error occurs. (Use the "unchecked" expression if you want to override this behaviour.)

3) Assignments from non-constant expressions of type int to byte require casts, because the compiler has no way of knowing that the result definitely fits in the byte.

4) The compound assignment operators automatically insert a cast to the operand type as part of their operation, precisely so that expressions like b |= whatever work as you'd expect.

Those four facts should explain all the behaviour that you guys have pointed out.


Is suspect that the line:

byte b = BIT_ZERO_SET | BIT_ONE_SET;

is actually processed by the C# compiler into an assignment of a constant value to b, rather than a bitwise operation - it can do this because the right side of the expression is fully defined at compile time.

The line:

//b = b | BIT_TWO_SET;

doesn't compiled because the bit-wise OR operator promotes its elements and evaluates to an int, not a byte. Since it involves a runtime value (b) it cannot be compiled into a constant assignment like the line before, and requires casting.


It is definitely strange, but what is happening, is the result of b|BIT_TWO_SET is an integer.

this works: b = (byte)(b | BIT_TWO_SET); because the result is an int in that case.

Also, you could replace that line with : b |= BIT_TWO_SET; which works.


        b = (byte)(b | BIT_TWO_SET);

is all you need to cast to make it compile, at least in Visual Studio 2008 against 2.0. It appears that | promotes the byte to int and you have to demote it again by hand.

Yep... a quick run past the standard shows that | returns int (or uint or long or ulong).


Instead of using

 b = b | BIT_TWO_SET;

use this:

 b |= BIT_TWO_SET;

funny huh.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜