6

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

ありがとう。

4

5 に答える 5

14

ここでのさまざまな答えは一般的に正しいですが、さまざまな事実があちこちに散らばっています。関連するポイントは次のとおりです。

1) バイト | の結果 | がないため、byte は int です。バイトで定義された演算子。

2) 整数のコンパイル時定数のみを含む計算は、「チェックされた」算術演算として扱われます。つまり、コンパイラは、定数の結果がオーバーフローしないことを確認します。この事実の良い結果は、コンパイル時の定数整数をより小さい型の変数または定数に代入すると、定数整数がより小さい型に適合することが自動的に検証されることです。存在する場合、割り当ては明示的なキャストなしで許可されます。そうでない場合は、コンパイル時エラーが発生します。(この動作をオーバーライドしたい場合は、「unchecked」式を使用してください。)

3) int 型の非定数式から byte への割り当てにはキャストが必要です。これは、コンパイラーが結果が確実に byte に収まることを知る方法がないためです。

4) 複合代入演算子は、操作の一部としてオペランド型へのキャストを自動的に挿入します。これにより、 b |= のような式が期待どおりに機能します。

これらの 4 つの事実は、皆さんが指摘したすべての動作を説明するはずです。

于 2009-10-14T21:39:24.840 に答える
7

それは間違いなく奇妙ですが、起こっているのb|BIT_TWO_SETは整数の結果です。

これは機能b = (byte)(b | BIT_TWO_SET);します。その場合、結果はintであるためです。

また、その行を:で置き換えることもできますb |= BIT_TWO_SET;

于 2009-10-14T18:51:38.627 に答える
7

次の行が疑われます:

byte b = BIT_ZERO_SET | BIT_ONE_SET;

は実際にはC#コンパイラによって処理され、ビット単位の演算ではなく、bへの定数値の割り当てになります。これは、式の右辺がコンパイル時に完全に定義されているために実行できます。

この線:

//b = b | BIT_TWO_SET;

ビット単位のOR演算子がその要素をプロモートし、バイトではなくintに評価されるため、コンパイルされません。実行時の値(b)が含まれるため、前の行のように定数の割り当てにコンパイルすることはできず、キャストが必要です。

于 2009-10-14T18:52:55.950 に答える
2
        b = (byte)(b | BIT_TWO_SET);

少なくともVisualStudio2008と2.0では、コンパイルするためにキャストする必要があるのはこれだけです。| バイトをintにプロモートし、手動で再度降格する必要があります。

うん...標準を超えてクイックランはそれを示しています| int(またはuintまたはlongまたはulong)を返します。

于 2009-10-14T18:54:21.523 に答える
1

使用する代わりに

 b = b | BIT_TWO_SET;

これを使って:

 b |= BIT_TWO_SET;

面白いね。

于 2009-10-14T18:57:22.453 に答える