2010-01-11 6 views
17

Je suis aux prises avec une résolution de surcharge de .net. J'ai écrit un petit échantillon de reproduire le problème:Résolution de surcharge de la méthode comportement inattendu

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 
} 

imprimera:

enum overload: 0 
object overload: 1 

Fondamentalement, la surcharge appelée est différente en fonction de la valeur (0, 1) au lieu du type de données .

Quelqu'un pourrait-il expliquer?

Mise à jour

Je aurais dû signaler qu'il ya un comportement différent entre C# 2 et C# 3

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

Répondre

16

Oui - la constante 0 est implicitement convertibles à tout type enum. La constante 1 est seulement explicitement convertible au type enum. Les deux sont implicitement convertibles en object (via la boxe) mais la conversion en enum est préférable là où elle est disponible.

Notez que cela a rien à voir avec avec quelles valeurs l'enum définit. La conversion pour toute valeur non nulle est explicite si elle correspond à une valeur dans l'énumération ou non. C'est juste un cas particulier pour la valeur 0, ce qui rend un autre code plus simple (en particulier lorsqu'il s'agit de drapeaux). Je n'ai pas les spécifications pour trouver la référence, j'en ai peur.

Étrangeté supplémentaire: en raison d'un bogue dans le compilateur MS (ne jamais être corrigé - il y aurait une rétrocompatibilité), il s'agit en fait de various zero constants, et pas seulement d'un nombre entier. Donc, Execute(0d) et Execute(0m) vont convertir un double et un nombre décimal à l'enum aussi. Cela ne fonctionne pas pour chaque constante - cela dépend de la nature exacte du code source. Tout est très étrange - suivez le lien où Eric Lippert révèle tout ...

+0

C'est très étrange. Je m'y attendais à ne pas compiler du tout, car les deux appels séparés à Execute sont ambigus. 0 et 1 sont des int, et il est donc également valable d'appeler la surcharge de l'objet ainsi que la surcharge MyEnum. – Nick

+0

je ne savais pas cela. pourquoi 0 est-il implicitement convertible en un type enum? dans l'exemple ici, 0 n'est pas une valeur valide. si quelque chose n'a pas de sens dans ma ligne de pensée, cela ne signifie pas nécessairement beaucoup (comme indiqué il y a 1 minute);) – hackerhasid

+0

@statichippo: C'est pratique dans quelques cas, comme après avoir effectué l'arithmétique bit à bit drapeaux. @Nick: Les deux méthodes sont * applicables *, mais la conversion de 0 à enum est "meilleure que" la conversion de 0 en objet par les règles de la spécification C# ... ce qui explique pourquoi cette surcharge est appelée. –

-1

Un Enum est juste mis en correspondance avec un int (par défaut). 0 ne correspond pas à votre Enum donc la surcharge qui prend un objet est utilisée. 1 correspond à votre énumération, de sorte que la surcharge Enum est utilisée.

Vous pouvez le faire:

Execute((object) 1); 

à la sortie

surcharge d'objet: 1

+2

Il semble que les résultats sont en fait le contraire de ce que vous attendez. La surcharge enum est frappée pour 0 et non pour 1. – mkedobbs

+0

Je viens juste de passer en revue ceci et j'ai réalisé que j'avais mal lu le message. Je pensais que 0 appelait "objet" et 1 appelait "enum". Je vais devoir regarder cela parce que ça n'a pas beaucoup de sens! – hackerhasid

+0

@statichippo: Cela prend tout son sens quand vous regardez la spécification et quelles conversions sont disponibles :) –

0

Je suis d'accord avec la réponse de Jon Skeet - se référer à son poste (ci-dessus) le 11 janvier à 17h32. Pour développer plus loin, s'il vous plaît se référer à C# spécification langage - page: 110

6.1.3 conversions d'énumération implicite Une conversion d'énumération implicite permet la décimale entier littéral 0 à convertir à tout type ENUM et à tout type nullable dont le type sous-jacent est un type enum. Dans ce dernier cas, la conversion est évaluée en convertissant au type enum sous-jacent et en enveloppant le résultat (§4.1.10).

Encore il y a un problème:

ajoutant l'instruction:

test.Execute (-0,0); // surcharge d'objet: 0

tout en ajoutant ce qui suit:

test.Execute (0,0); // surcharge Enum: 0

Jacques Colmenero Enterprise Architect [email protected]