2012-07-17 14 views
6

Perché i seguenti due esempi di codice producono output diversi?Sovraccarico di un metodo nella sottoclasse (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(); 
    } 
} 

uscita:

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

uscita:

012.351.
Func(EnumType) 
Func(EnumType) 

Sono perplesso. Significa che Func (EnumType) nasconde Func (int) dichiarato nella base? Se questo è il caso, perché il letterale 0 è implicitamente assegnato a EnumType nel secondo caso senza un avviso?

EDIT:

C'è un comportamento ancora più interessante quando provo

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

Qual è il tuo indovinare l'uscita dovrebbe essere simile?

qui è:

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

Tutte le idee perché 0 e 1 vengono trattati in modo diverso?

EDIT 2:

Si scopre che letterale 0 ha infatti un significato speciale in C#.

Here e here Ho trovato un'eccellente descrizione di questo comportamento (vedere le risposte accettate).

risposta

5

Sì, nasconde Func (int) dichiarato in classe A.

Inoltre, vedere enum (C# Reference)

Il tipo sottostante di default degli elementi di enumerazione è int

Si potrebbe anche voler dare un'occhiata al Polymorphism (C# Programming Guide)

EDIT

Se è necessario modificare

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)); 

vi accorgerete che l'uscita dovrebbe essere

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

sembrerebbe che 0 è implicitamente fusa al valore di default enum se passati direttamente alla chiamata di funzione .

EDIT 2

ho controllato il codice IL e sembra che proietta implicitamente il 0 a un'enumerazione

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

perché non vi è alcun avviso sulla conversione implicita da int (0) a EnumType? – alexm

+0

Si potrebbe voler leggere un po 'di più sulle conversioni implicite http://msdn.microsoft.com/en-us/library/aa691280(v=vs.71) –

+0

@atander: c'è ancora una differenza "magica" tra 0 e 1 (vedi la mia domanda modificata). È documentato da qualche parte? – alexm

0

Il tipo sottostante dell'enumerazione è int, quindi la funzione ClassB nasconde la versione ClassA.

Prova a cambiare a questo:

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

Si dovrebbe vedere chiama la funzione int invece.