簡體   English   中英

C#字節添加操作

[英]C# byte addition operation

有人能指出我,為什么在這里:

Byte b = 100; 
b = (Byte)(b+200);

我必須使用顯式類型轉換。 但在這兒

Byte b = 100;
b += 200;

我不需要這樣做?

編譯器是否為這兩種情況生成不同的IL代碼? 哪種情況更好?

因為標准允許它(見下面的第二種情況):

14.14.2復合賦值

x op = y形式的操作通過應用二元運算符重載決策(第14.2.4節)來處理,就像操作是用x op y編寫的一樣。 然后,

  • 如果所選運算符的返回類型可隱式轉換為x的類型,則操作將計算為x = x op y ,但x僅計算一次。

  • 否則,如果所選運算符是預定義運算符,如果所選運算符的返回類型可顯式轉換為x類型,並且如果y可隱式轉換為x類型或運算符是移位運算符,則操作被評估為x = (T)(x op y) ,其中Tx的類型,除了x僅被計算一次。

  • 否則,復合賦值無效,並發生編譯時錯誤。

在這種情況下,IL代碼應該基本相同。 當然,如果評估b有副作用,它將在b = (byte)b + 200情況下評估兩次,並且在使用復合賦值時僅評估一次。

這是C#標簽中的FAQ,很難找到重復。 首先需要演員陣容。 根本原因是CLI僅為Opcodes.Add IL指令指定了有限數量的有效類型。 僅支持Int32,Int64,Single,Double和IntPtr類型的操作數。 IntPtr也很特別,C#語言禁止使用那個。

因此,C#編譯器必須使用隱式轉換將字節提升為運算符支持的類型。 它將選擇Int32作為最接近的兼容類型。 添加的結果是Int32。 在不截斷結果的情況下,它不適合返回一個字節,丟掉額外的位。 一個明顯的例子是255 + 1,Int32中的結果是256但是不適合字節並且在存儲時產生0。

這是一個問題,語言設計者不喜歡在沒有你明確承認你意識到后果的情況下發生截斷。 需要使用強制轉換來說服編譯器您知道。 當然,你需要機械地制作演員, 而不必過多考慮后果。 但這使它成為你的問題,而不是微軟的:)

rub是+ =運算符,是一個非常好的運算符來編寫壓縮代碼。 類似於var關鍵字的簡潔性。 岩石和堅硬的地方然而,你把演員放在哪里? 它只是不起作用,所以他們懲罰問題,並允許截斷沒有演員表。

值得注意的是VB.NET的工作方式,它不需要強制轉換。 但它保證了C#默認不提供,當結果不適合時會產生OverflowException。 非常好,但該檢查不是免費的。

設計干凈的語言是一個非常難的問題。 C#團隊做得非常出色,但不能承受瑕疵。 否則是處理器設計帶來的那種疣。 IL具有這些類型限制,因為這也是真正的32位處理器,特別是90年代流行的RISC設計。 它們的內部寄存器只能處理32位整數和IEEE-754浮點。 並且只允許較小類型的裝載和存儲。 Intel x86內核非常受歡迎,實際上允許在較小類型上進行基本操作。 但這主要是一個歷史性事故,因為英特爾通過8位8080和16位8086代保持設計兼容。 它不是免費的,16位操作需要額外的cpu周期。 要避免。

這是因為隱式轉換規則。

當您有二元+運算符時,結果將轉換為兩種類型中較大的一種。 文字200的類型為int,因此表達式b+200的類型為int。 賦值運算符=不進行隱式轉換,而是拋出錯誤。 如在

        int x = 10;
        Byte b = x; //Error

在第二種情況下, +=運算符需要字節,所以200(其類型為int,但適合字節)被隱式轉換為字節,因為編譯器知道它可以。 以下將不會編譯,因為編譯不知道x是否適合一個字節。

        Byte b = 100;
        int x = 200;
        b += x; //Error

如果你制作xa const,那么它會編譯:

        Byte b = 100;
        const int x = 200;
        b += x;  //OK

該規范將此視為復合賦值運算符的特定情況:

http://msdn.microsoft.com/en-us/library/aa691316%28v=vs.71%29.aspx

具體來說,子彈2:

  • 否則,如果所選運算符是預定義運算符,如果所選運算符的返回類型可顯式轉換為x類型,並且如果y可隱式轉換為x類型,則操作將計算為x =(T )(x op y),其中T是x的類型,除了x僅被計算一次。

上面的第二條規則允許在某些上下文中將x op = y計算為x =(T)(x op y)。 存在這樣的規則:當左操作數是sbyte,byte,short,ushort或char類型時,預定義運算符可以用作復合運算符。 即使兩個參數都屬於這些類型之一,預定義運算符也會生成int類型的結果,如第7.2.6.2節中所述。 因此,如果沒有強制轉換,則無法將結果分配給左操作數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM