2009-10-14 23 views
4

我在C#編譯器中發現了一個奇怪的情況。爲什麼需要投下?C#按位或需要使用字節鑄造*有時*

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();  
    } 
} 

謝謝。

回答

6

的嫌疑,該行:

byte b = BIT_ZERO_SET | BIT_ONE_SET; 

實際上是由C#編譯器處理成一個恆定值賦值給b,而不是按位操作 - 它可以做到這一點,因爲的右側表達式在編譯時完全定義。

行:

//b = b | BIT_TWO_SET; 

不編譯因爲逐位或運算促進其元素和評估爲int,而不是一個字節。由於它涉及運行時間值(b),因此無法像之前的行一樣編譯爲常量賦值,並且需要轉換。

+0

這很有道理...... – Nate 2009-10-14 18:54:37

+0

+1,是的,編譯器會在編譯時計算常量表達式。這解釋了爲什麼第一個作業不會給出錯誤。 – 2009-10-14 18:56:44

+0

@Godeke:你怎麼和他說什麼不一樣?他的意思是,在一個字節上的一個按位「或」的結果值是一個整數。 – 2009-10-14 18:59:33

7

這絕對是奇怪的,但是發生了什麼事情,結果是b|BIT_TWO_SET是一個整數。

此作品:b = (byte)(b | BIT_TWO_SET);,因爲在這種情況下結果是int。

另外,你可以用:b |= BIT_TWO_SET;取代該行。

+0

我不知道有一個| =。謝謝! – Nate 2009-10-14 18:53:10

+0

'x | = y'和'x&=〜y'是您的位操作的朋友。 – 2009-10-14 19:06:07

2
 b = (byte)(b | BIT_TWO_SET); 

是您需要進行編譯的所有東西,至少在Visual Studio 2008中是2.0。它似乎|將字節提升爲int,並且您必須手動將其降級。

是的......快速跑過標準顯示|返回int(或uint或long或ulong)。

+0

是的,我意識到後改變了我的帖子。謝謝。 – Nate 2009-10-14 18:55:44

0

而不是使用

b = b | BIT_TWO_SET; 

使用這個的:

b |= BIT_TWO_SET; 

搞笑呵呵。

12

這裏的各種答案通常都是正確的,但是在整個地方都有一堆不同的事實。相關要點如下:

1)字節|字節是一個int,因爲沒有|運算符在字節上定義。 2)僅涉及積分編譯時常量的計算被視爲「檢查」算術;也就是說,編譯器驗證常數結果不會溢出,等等。這個事實的一個令人愉快的結果是,將編譯時常量整數賦值給變量或較小類型的常量會自動驗證該常量整數是否適合較小類型。如果確實如此,那麼可以在沒有明確演員的情況下分配任務。如果沒有,則會發生編譯時錯誤。 (如果要覆蓋此行爲,請使用「未選中」表達式。)

3)從int類型的非常量表達式分配給字節需要強制轉換,因爲編譯器無法知道結果是否適合字節。

4)複合賦值操作符會自動在操作數類型中插入一個強制類型作爲其操作的一部分,這樣就可以像b | = whatever這樣的表達式按照您的期望工作。

這四個事實應該解釋你們所指出的所有行爲。