在子类中重载方法(枚举 vs int)

6
为什么以下两个代码示例会产生不同的输出? 情况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)

Case 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(int)被Func(EnumType)隐藏了?如果是这种情况,那么为什么第二个例子中文字面量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: 事实证明,在C#中,字面上的0确实具有特殊含义。
在此链接链接中,我找到了一个对这种行为的优秀描述(请参见被接受的答案)。
2个回答

5

是的,它隐藏了类A中声明的Func(int)。

此外,请参阅 enum (C# Reference)

枚举元素的默认基础类型是int

您可能还想查看 多态性 (C# 编程指南)

编辑

如果您更改

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

to

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

为什么在从int(0)到EnumType的隐式转换中没有警告? - alexm
你可能想多了解一下隐式转换,可以参考以下链接:http://msdn.microsoft.com/zh-cn/library/aa691280(v=vs.71) - Adriaan Stander
@atander:0和1之间仍然存在“神奇”的差异(请参见我编辑后的问题)。这是否有记录在某个地方? - alexm
如果直接传递给函数调用的话,似乎0会被隐式转换为默认枚举值。我倾向于这种解释并接受你的答案。谢谢! - alexm

0

枚举的底层类型是 int,因此 ClassB 函数确实隐藏了 ClassA 版本。

尝试将其更改为以下内容:

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

你应该看到它调用了 int 函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接