2012-07-17 17 views
6

¿Por qué las siguientes dos muestras de código producen resultados diferentes?Sobrecarga de un método en la subclase (Enum vs int)

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

de salida:

Func(int) 
Func(EnumType) 

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

de salida:

Func(EnumType) 
Func(EnumType) 

Estoy perplejo. ¿Significa que Func (EnumType) oculta Func (int) declarado en la base? Si este es el caso, ¿por qué el literal 0 es implícitamente enviado a EnumType en el segundo caso sin una advertencia?

EDIT:

No es un comportamiento aún más interesante cuando intento

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

¿Cuál es su conjetura la salida debe ser similar?

aquí está:

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

Cualquier idea por qué 0 y 1 son tratados de manera diferente?

EDIT 2:

Resulta que literal 0 de hecho tiene un significado especial en C#.

Here y here Encontré una excelente descripción de este comportamiento (ver las respuestas aceptadas).

Respuesta

5

Sí, oculta el Func (int) declarado en la clase A.

Además, consulte enum (C# Reference)

El tipo subyacente predeterminado de elementos de enumeración es int

También puede ser que desee echar un vistazo a Polymorphism (C# Programming Guide)

EDITAR

Si cambiaras

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

a

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

se encuentra que la salida debe ser

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

parecería que 0 es fundido implícitamente al valor de enumeración por defecto si se pasa directamente a la llamada de función .

EDIT 2

he comprobado el código IL Y parece que implícitamente arroja el 0 a una enumeración

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

¿por qué no hay ninguna advertencia en la conversión implícita de int (0) a EnumType? – alexm

+0

Es posible que desee leer más acerca de las conversiones implícitas http://msdn.microsoft.com/en-us/library/aa691280(v=vs.71) –

+0

@atander: todavía hay una diferencia "mágica" entre 0 y 1 (ver mi pregunta editada). Está documentado en alguna parte? – alexm

0

El tipo subyacente de la enumeración es int, por lo que la función ClassB oculta la versión ClassA.

trate de cambiar a esto:

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

Debería ver que llama a la función int en lugar.