2010-01-11 13 views
17

Sto combattendo con una strana risoluzione, almeno per me, del metodo .net. Ho scritto un piccolo campione di riprodurre il problema:Comportamento imprevisto di overload del metodo

class Program 
{ 
    static void Main(string[] args) 
    { 
     var test = new OverloadTest(); 
     test.Execute(0); 
     test.Execute(1); 

     Console.ReadLine(); 
    } 
} 

public class OverloadTest 
{ 
    public void Execute(object value) 
    { 
     Console.WriteLine("object overload: {0}", value); 
    } 

    public void Execute(MyEnum value) 
    { 
     Console.WriteLine("enum overload: {0}", value); 
    } 
} 

public enum MyEnum 
{ 
    First = 1, Second = 2, Third = 3 
} 

stamperà:

enum overload: 0 
object overload: 1 

Fondamentalmente il sovraccarico di chiamata è diverso a seconda del valore (0, 1) al posto di un dato tipo di dati .

Qualcuno potrebbe spiegare?

Aggiornamento

avrei fatto notare che c'è un diverso comportamento tra C# 2 e C# 3

Do((long)0) => object overload //C# 2 
Do((long)0) => enum overload //C# 3 

risposta

16

Sì - la costante 0 è implicitamente convertibile in qualsiasi tipo enum. La costante 1 è solo esplicitamente trasformabile in tipo enum. Entrambi sono implicitamente convertibili in object (tramite boxing) ma la conversione all'enum è preferibile dove è disponibile.

Si noti che questo ha nulla da fare da fare con i valori definiti dall'enumerazione. La conversione per qualsiasi valore diverso da zero è esplicita indipendentemente dal fatto che corrisponda a un valore nell'enumerazione o meno. È solo un caso speciale per il valore 0, che rende più semplice un altro codice (in particolare quando si tratta di flag). Non ho le specifiche disponibili per trovare il riferimento, temo.

Bonus stranezza: a causa di un bug nel compilatore MS (non essere mai riparato - si romperebbe la compatibilità con le versioni precedenti) in realtà è various zero constants, non solo un numero intero. Quindi Execute(0d) e Execute(0m) convertiranno anche un enumerazione decimale e l'enum. Non funziona per ogni costante di zero - dipende dalla natura esatta del codice sorgente. È tutto molto strano - segui il link in cui Eric Lippert rivela tutto ...

+0

Questo è molto strano. Mi sarei aspettato che non si compilasse affatto, perché le due chiamate separate a Execute sono ambigue. 0 e 1 sono int, quindi è ugualmente valido chiamare sovraccarico di oggetti e sovraccarico di MyEnum. – Nick

+0

non lo sapevo. perché 0 è implicitamente convertibile in qualsiasi tipo di enum? nell'esempio qui, 0 non è un valore valido. se qualcosa non ha senso per la mia linea di pensiero, ciò non significa necessariamente molto (sebbene indicato 1 minuto fa);) – hackerhasid

+0

@statichippo: È utile in alcuni casi, ad esempio dopo aver eseguito l'aritmetica bit per bit su bandiere. @Nick: Entrambi i metodi sono * applicabili *, ma la conversione da 0 a enum è "migliore di" la conversione da 0 a oggetto dalle regole della specifica C# ... che è il motivo per cui viene chiamato quel sovraccarico. –

-1

un enum è solo mappato ad un int (per impostazione predefinita). 0 non si connette all'Enum in modo che venga utilizzato il sovraccarico che prende un oggetto. 1 mappa il tuo enum in modo che venga utilizzato il sovraccarico Enum.

Si potrebbe fare questo:

Execute((object) 1); 

all'uscita

sovraccarico oggetto: 1

+2

Sembra che i risultati sono in realtà l'opposto di quello che ci si aspetta. Il sovraccarico di enum viene colpito per 0 e non per 1. – mkedobbs

+0

Ho appena passato questo e ho capito di aver letto male il post. Ho pensato che 0 stava chiamando "oggetto" e 1 stava chiamando "enum". Dovrò esaminarlo perché _that_ non ha molto senso! – hackerhasid

+0

@statichippo: Ha perfettamente senso quando si guardano le specifiche e quali sono le conversioni disponibili :) –

0

Sono d'accordo con la risposta di Jon Skeet - fai riferimento al suo post (sopra) l'11 gennaio alle 17:32. Per espandere ulteriormente, si prega di fare riferimento a C# linguaggio di specifica - pagina: 110

6.1.3 implicita La conversione di enumerazione una conversione enumerazione implicita permette decimale-integer letterale 0 per essere convertito in qualsiasi enum-tipo e a qualsiasi tipo nullable il cui tipo sottostante sia di tipo enum. In quest'ultimo caso, la conversione viene valutata convertendo il tipo di enum sottostante e avvolgendo il risultato (§4.1.10).

ancora non v'è un problema:

aggiungendo la dichiarazione:

test.Execute (-0.0); // sovraccarico oggetto: 0

aggiungendo la seguente:

test.Execute (0,0); // sovraccarico enum: 0

Jacques Colmenero Enterprise Architect [email protected]

Problemi correlati