web-dev-qa-db-ja.com

C#intバイト変換

なぜ

byte someVar;
someVar -= 3; 

有効だが

byte someVar;
someVar = someVar - 3;

じゃない?

28
Dested

驚くべきことに、バイトに対して操作を実行すると、int値を使用して計算が行われ、バイトは最初に暗黙的に(int)にキャストされます。これはshortsにも当てはまり、同様に、浮動小数点演算を行うときにfloatsはdoubleにアップコンバートされます。

2番目のスニペットは次と同等です:

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

このため、コンパイラーが割り当てを受け入れるようにするには、結果を(byte)にキャストする必要があります。

someVar = (byte) (someVar - 3);
30
John Kugelman

タイプA op Bのバイナリ数値演算子で有効なオペランドを指定するCLI仕様(Ecma 335)の表のコピーを次に示します。ここで、AとBはオペランドで、「op」は演算子(Opcodesなど)です。スニペットで使用しているサブ:

alt text

これにはいくつかの注釈が必要です。

  • 「ネイティブint」はC#プログラムのIntPtrです
  • [〜#〜] f [〜#〜]は、C#のdoubleまたはfloatの浮動小数点型を表します
  • はポインター値を表し、ボックスは安全でない操作であるため影付きです
  • [〜#〜] o [〜#〜]はオブジェクト参照を表します
  • xは許可されていない操作です。

[〜#〜] f [〜#〜]の行と列に注意してください。両方のオペランドは浮動小数点である必要があります。たとえば、doubleにintを直接追加することはできません。 C#コンパイラは、演算子が有効になるようにintオペランドを自動的にdoubleに変換することにより、この制限に対処します。

あなたの質問に関連する:また、byte、sbyte、char、short、およびushortタイプが存在しないことにも注意してください。同じアプローチで、コンパイラーは、演算子を使用できるように、オペランドを値を表すことができる最小の型に変換します。これはint32になります。表によると、操作の結果はint32になります。

さて、こっちはこっちです:結果はint32ですが、それをバイト値に戻すには狭い変換が必要です。 32ビットから8ビットまで。かなりのビットを失うため、それは問題です。 C#コンパイラでは、明示的に指定する必要があります。あなたは基本的に、自分が何をしているかを知っていること、そして潜在的に驚くべき結果に気づいていることを認めます。このように:

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

必要なキャストを適用する効果的な方法がないため、-=演算子は問題です。言語の構文では表現できません。 (byte)3を使用しても意味がありません。とにかくリテラルはint32に変換され、演算子が機能します。

彼らは問題をパントし、コンパイラはあなたの助けなしに自動的にキャストを出します。

11
Hans Passant