2012-07-17 41 views
6

为什么以下两个代码示例产生不同的输出?重载子类中的方法(Enum vs int)

案例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)?如果是这种情况,那么为什么立即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#中的特殊含义。

Herehere我发现了这种行为的一个很好的描述(请参阅接受的答案)。

回答

5

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

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

默认基础类型的枚举元素的数据类型为int

你可能也想看看Polymorphism (C# Programming Guide)

编辑

如果您可以更改

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 
+0

为什么没有关于从int(0)到EnumType的隐式转换的警告? – alexm 2012-07-17 04:41:01

+0

您可能想要阅读更多关于隐式转换的内容http://msdn.microsoft.com/zh-cn/library/aa691280(v=vs.71) – 2012-07-17 04:54:22

+0

@atander:0和1之间仍然存在“魔术”差异(见我编辑的问题)。它是否记录在某处? – alexm 2012-07-17 05:01:19

0

基础类型枚举的为int,所以ClassB的功能确实隐藏了ClassA版本。

尝试更改为此:

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

你应该看到它调用INT函数。