2010-09-04 172 views

回答

29

令人驚訝的是,當您對字節執行操作時,計算將使用int值完成,其中字節首先隱式轉換爲(int)。對於short s也是如此,並且在執行浮點算術時,float s同樣被上轉換爲double

第二個片段是等價於:

byte someVar; 
someVar = (int) someVar - 3; 

因此必須把結果返回到(byte),讓編譯器承擔的任務。

someVar = (byte) (someVar - 3); 
+0

有人可以驗證類型轉換是否發生在someVar- = 3的IL級別;例?它是否生成相同的IL代碼? – Dested 2010-09-04 07:29:23

+2

我剛剛檢查了反射器。 ' - ='運算符在IL級別生成'conv.u1',這就是爲什麼第一個代碼段正在工作的原因 – 2010-09-04 13:51:00

+5

@Dested精確的規則在C#語言規範中給出。它規定:_「上面的第二個規則允許'x op = y'在某些上下文中被評估爲'x =(T)(x op y)'。規則的存在使得預定義的操作符可以用作複合操作符當左操作數是'sbyte','byte','short','ushort'或'char'類型時,即使兩個參數都是這些類型之一,預定義的運算符也會產生類型爲「int」 ,如第7.3.6.2節所述,因此,如果沒有強制轉換,則不能將結果賦給左操作數。「_ – 2013-01-04 12:35:10

11

這裏的一個表中的CLI規範(ECMA 335)指定哪些操作數上的類型A的運算B,其中A和B是操作數和「OP」的二進制數值運算符有效副本是運營商,像Opcodes.Sub您正在使用您的片段:

alt text

一些註釋需要用這樣的:

  • 「原生INT」 是在的IntPtr C#程序
  • ˚F表示浮點型,雙或漂浮在C#
  • &表示的指針值,所述框被陰影,因爲它們是不安全的操作
  • ö表示一個對象引用
  • x是不允許的操作。

注意事項˚F的行和列,兩個操作數必須浮點,你不能直接添加,即int的兩倍。 C#編譯器通過自動將int操作數轉換爲double來處理該限制,以便操作符有效。

與你的問題有關:還要注意字節,sbyte,char,short和ushort類型不存在。同樣的方法,編譯器將操作數轉換爲可以表示值的最小類型,以便可以使用操作符。這將是int32。根據該表,該操作的結果將是int32。

現在,這裏是擦:結果是int32,但將它分配給一個字節值需要一個縮小轉換。從32位到8位。這很麻煩,因爲它失去了重要的位。 C#編譯器要求您明確說明。你基本上承認你知道你在做什麼,並且你意識到了可能出人意料的結果。像這樣:

byte v = 255; 
v = (byte)(v + 1); 

- =操作符是一個問題,因爲沒有有效的方法來應用所需的強制轉換。它在語言語法中不可表達。使用(字節)3沒有意義,文字無論如何都轉換爲int32以使操作符工作。

他們解決了這個問題,編譯器會自動發出投射而無需您的幫助。

+0

這解釋了爲什麼我無法使用反射來在類型之間隱式轉換。 – fusi 2015-09-03 13:18:05