6

次の2つのコードサンプルが異なる出力を生成するのはなぜですか?

ケース1

enum EnumType
{
    First,
    Second,
    Third
}

class ClassB
{
    public string Func(int index)
    {
        return "Func(int)";
    }

    public string Func(EnumType type)
    {
        return "Func(EnumType)";
    }
}

class Program
{
    static void Main(string[] args)
    {
        ClassB b = new ClassB();
        Console.WriteLine(b.Func(0));
        Console.WriteLine(b.Func(EnumType.First));
        Console.ReadLine();
    }
}

出力:

Func(int)
Func(EnumType)

ケース2

enum EnumType
{
    First,
    Second,
    Third
}

class ClassA
{
    public string Func(int index)
    {
        return "Func(int)";
    }
}

class ClassB : ClassA
{
    public string Func(EnumType enumType)
    {
        return "Func(EnumType)";
    }
}

class Program
{
    static void Main(string[] args)
    {
        ClassB b = new ClassB();
        Console.WriteLine(b.Func(0));
        Console.WriteLine(b.Func(EnumType.First));
        Console.ReadLine();
    }
}

出力:

Func(EnumType)
Func(EnumType)

困惑しています。Func(EnumType)がベースで宣言されたFunc(int)を非表示にすることを意味しますか?この場合、2番目のケースで警告なしにリテラル0が暗黙的にEnumTypeにキャストされるのはなぜですか?

編集:

私が試してみると、さらに興味深い行動があります

Console.WriteLine(b.Func(0));         
Console.WriteLine(b.Func(1));
Console.WriteLine(b.Func(EnumType.First));

出力はどのようになると思いますか?

ここにあります:

 Func(EnumType)
 Func(int)
 Func(EnumType)

0と1の扱いが異なる理由はありますか?

編集2:

リテラル0は確かにC#で特別な意味を持っていることがわかります。

ここここで、私はこの振る舞いの優れた説明を見つけました(受け入れられた答えを参照してください)。

4

2 に答える 2

5

はい、クラスAで宣言されたFunc(int)を非表示にします。

さらに、列挙型(C#リファレンス)を参照してください

列挙型要素のデフォルトの基になるタイプはintです

ポリモーフィズム(C#プログラミングガイド)もご覧ください。

編集

変更する場合

Console.WriteLine(b.Func(0));          
Console.WriteLine(b.Func(1)); 
Console.WriteLine(b.Func(EnumType.First)); 

int i = 0;
Console.WriteLine(b.Func(i));          
Console.WriteLine(b.Func(1)); 
Console.WriteLine(b.Func(EnumType.First)); 

出力は次のようになります。

Func(int)   
Func(int)   
Func(EnumType)

関数呼び出しに直接渡された場合、0は暗黙的にデフォルトの列挙値にキャストされるように見えます。

編集2

ILコードを確認しましたが、暗黙的に0を列挙型にキャストしているようです。

IL_0000: nop
IL_0001: newobj instance void ClassB::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldc.i4.0
IL_0009: callvirt instance string ClassB::Func(valuetype EnumType)
IL_000e: call void [mscorlib]System.Console::WriteLine(string)
IL_0013: nop
IL_0014: ldloc.0
IL_0015: ldc.i4.0
IL_0016: callvirt instance string ClassB::Func(valuetype EnumType)
IL_001b: call void [mscorlib]System.Console::WriteLine(string)
IL_0020: nop
IL_0021: call string [mscorlib]System.Console::ReadLine()
IL_0026: pop
IL_0027: ret
于 2012-07-17T04:33:06.717 に答える
0

列挙型の基になるタイプはintであるため、ClassB関数はClassAバージョンを非表示にします。

これに変更してみてください:

enum EnumType : byte
{
    First,
    Second,
    Third
}
...
Console.WriteLine(b.Func(256));  // out of range for a byte

代わりにint関数を呼び出すことがわかります。

于 2012-07-17T04:35:26.777 に答える