26

C# コンパイラが 2 番目の if ステートメントに対してのみエラー メッセージを表示する理由を知りたいです。

enum Permissions : ulong
{
    ViewListItems = 1L,
}

public void Method()
{
    int mask = 138612833;
    int compare = 32;

    if (mask > 0 & (ulong)Permissions.ViewListItems > 32)
    {
        //Works
    }

    if (mask > 0 & (ulong)Permissions.ViewListItems > compare)
    {
        //Operator '>' cannot be applied to operands of type 'ulong' and 'int'
    }
}
4

3 に答える 3

32

ILSpyを使用して出力を調べてこれを実験してきましたが、これが私が発見したものです。

明らかに、2番目のケースでは、これはエラーです。両方を強制できるタイプがないため、ulongとを比較することはできません。intAulongは、に対して大きすぎる可能性がlongあり、intは負の可能性があります。

ただし、最初のケースでは、コンパイラーは巧妙です。1const > const32は決して真ではなくif、コンパイルされた出力にステートメントがまったく含まれていないことを認識しています。(到達不能コードに対して警告を出す必要があります。)const intリテラルではなくを定義して使用する場合、またはリテラルを明示的にキャストする場合でも同じです(つまり(int)32)。

しかし、コンパイラーは、先ほど不可能だと言っulongた、とを正常に比較していませんか?int

どうやらそうではありません。では、何起こっているのでしょうか。

代わりに、次の行に沿って何かをしてみてください。(コンパイラーが何もコンパイルしないように、入力を取得して出力を書き込みます。)

const int thirtytwo = 32;
static void Main(string[] args)
{
    ulong x = ulong.Parse(Console.ReadLine());
    bool gt = x > thirtytwo;
    Console.WriteLine(gt);
}

これはulong、が変数であり、コンパイル時に結果が不明であっても、コンパイルされます。ILSpyの出力を見てください。

private static void Main(string[] args)
{
    ulong x = ulong.Parse(Console.ReadLine());
    bool gt = x > 32uL;        /* Oh look, a ulong. */
    Console.WriteLine(gt);
}

したがって、コンパイラは実際にはあなたconst intをとして扱っていますulong。を作成すると、それが常にthirtytwo = -1であることがわかっていても、コードのコンパイルに失敗します。コンパイラ自体は、をと比較することはできません。gtulongint

また、の代わりにを作成するxと、コンパイラは整数ではなく生成しますが、整数として生成する必要はありませ。(実行時にとを比較できます。)longulong32L32intlong

これは、コンパイラが最初のケースで32として扱わないことを示しています。これは、コンパイラが。のタイプと一致する可能性があるという理由だけで、そうしなければならないためです。これにより、ランタイムが定数を強制する必要がなくなります。これは、権利によって強制が不可能な場合の単なるボーナスです。ulongx

于 2012-06-18T15:47:07.943 に答える
21

このエラーメッセージを表示するのはCLRではなく、コンパイラです。

最初の例では、コンパイラは(または暗黙的にegに変換可能な型)32として扱いますが、2番目の例では、型を明示的に宣言しました。とを受け入れる演算子のオーバーロードがないため、コンパイラエラーが発生します。ulongulonguintint>ulongint

于 2012-06-18T15:48:24.543 に答える
3

rich.okelly と rawling の回答は、それらを直接比較できない理由については正しいです。ConvertクラスのToUInt64メソッドを使用して int をプロモートできます。

if (mask > 0 & (ulong)Permissions.ViewListItems > Convert.ToUInt64(compare))
{
}
于 2012-06-18T15:57:24.773 に答える