12

この奇妙な行動を私に説明できる人はいますか?

    int i = 0x1234;
    byte b1 = (byte)i;
    byte b2 = (byte)0x1234;         //error: const value '4660' can't convert to byte (use unchecked)
    byte b3 = unchecked((byte)0x1234);
    byte b4 = checked((byte)i);     //throws
    byte b5 = (byte)(int)0x1234;    //error: same as above

注:これは空のコンソールアプリケーションであり、算術チェックは有効になっていません(デフォルトでは)。よろしくお願いします。

編集:私は十分に明確であるはずでしたが、すべてではありません。

単語がバイトに収まらないことを私は知っています。ただし、デフォルトでは、C#プログラムでは、主にパフォーマンス上の理由から、特定の「危険な」操作が許可されています。

同様に、2つの大きな整数を合計して、オーバーフローがまったくない場合があります。

私の不思議は、上記のコンパイル時エラーについてでした。b1キャスト/割り当てがコンパイルされ、b2がコンパイルできません。どちらも同じ値のInt32であるため、明らかに違いはありません。

それが今はっきりしていることを願っています。

4

3 に答える 3

15

C#4仕様のセクション7.19の一部につまずきます。

定数式が明示的にuncheckedコンテキストに配置されていない限り、式のコンパイル時の評価中に積分型の算術演算および変換で発生するオーバーフローは、常にコンパイル時のエラーを引き起こします。

基本的に、実行時に操作がオーバーフローすることを許可しても、コンパイル時にターゲットタイプに変換できない定数式を使用しようとしている場合は、次のように指示する必要があります。あなたが何をしているのかを本当に知っているコンパイラ。

たとえば、この場合、情報が失われます-それは次のようになります

byte b3 = 0x34;

したがって、読者を誤解させないより明確なコードを提供するために、通常はそれを指定する方がよいでしょう。定数でオーバーフローすることは比較的まれです。ほとんどの場合、代わりに有効な値を指定する必要があります。

于 2011-10-19T14:58:08.580 に答える
1

これは奇妙な動作ではありません。バイトデータ型の変数の有効な範囲はです0-255が、HEX0x1234値を10進法に変換すると次のようになり4660ます。したがって、チェックされていない 場合は、オーバーフローチェックの積分型の算術演算と変換を制御するために使用されます。

最終的なハッシュコードを計算するために数値演算を行う実装でuncheckedよく使用されることがわかります。GetHashCode()

要約するとunchecked、整数型演算の最終結果値は重要ではないが、オーバーフローが発生する可能性がある場合に使用する必要があります。

于 2011-10-19T14:57:26.527 に答える
1

これをチェックなしで囲むべきではありません。チェックを外すと、危険な値型を型に割り当てることができ、オーバーフローが発生する可能性があります。

byte b1 = (byte)i;実行時にオーバーフローまたはキャスト例外が発生します。

byte b2 = (byte)0x1234;0xFFより大きい値をバイトに格納できないため、は無効です。

byte b3 = unchecked((byte)0x1234);0x34または0x12(CLRの実装に応じて)をb3に配置し、他のバイトはオーバーフローします。0x1234をintにキャストし、それをbyteにキャストしようとする

byte b4 = checked((byte)i);のと同じです。byte b1 = (byte)i;

byte b5 = (byte)(int)0x1234;繰り返しますが、0x1234は大きすぎるため、バイトに変換できません。

于 2011-10-19T14:59:34.377 に答える