35 votes

Pourquoi le compilateur C# utilisation d'une méthode non valide de la surcharge?

J'ai été confondu par le code suivant

class A
{
    public void Abc(int q)
    {
        Console.Write("A");
    }
}

class B : A
{
    public void Abc(double p)
    {
        Console.Write("B");
    }
}

    ...
    var b = new B();
    b.Abc((int)1);

Le résultat de l'exécution de code est "B", écrit à la console.

En fait, la classe B contient deux surcharges de la méthode Abc, le premier pour un paramètre de type int, la seconde de double. Pourquoi le compilateur d'utiliser un double version pour un argument entier?

Attention la méthode abc(double) n'a pas d'ombre ou de remplacer la méthode abc(int)

54voto

hatchet Points 7251

Depuis, le compilateur peut convertir implicitement le type int en double, il choisit la B. méthode Abc. Ceci est expliqué dans ce post par Jon Skeet (de la recherche pour "implicite"):

La cible de l'appel de méthode est une expression de type Enfant, de sorte que le le compilateur cherche d'abord à l'Enfant de la classe. Il n'y a qu'une seule méthode il y a, et c'est le cas (il y a une conversion implicite de type int pour double) alors que c'est celui qui est ramassé. Le compilateur n'a pas considérons la méthode Parent à tous.

La raison pour cela est de réduire le risque de fragile de la classe de base problème...

Plus de Eric Lippert

Comme le standard dit, "méthodes dans une classe de base ne sont pas des candidats si une méthode dans une classe dérivée est applicable".

En d'autres termes, la résolution de surcharge de l'algorithme commence par la recherche la classe d'une méthode applicable. Si il en trouve un, puis tous les autres méthodes applicables dans le plus profond des classes de base sont retirés de la ensemble candidat pour la résolution de surcharge. Depuis Le Delta.Frob(float) est échéant, Charlie.Frob(int) est même jamais considéré comme un candidat. Seulement si non applicable, les candidats sont trouvés dans la plupart des dérivés de type ne nous partons à la recherche à sa classe de base.

Les choses deviennent un peu plus intéressantes, si nous prolongeons l'exemple de votre question avec cette classe supplémentaire qui descend d'Un:

class C : A {
    public void Abc(byte b) {
        Console.Write("C");
    }
}

Si nous exécutons le code suivant

int i = 1;
b.Abc((int)1);
b.Abc(i);
c.Abc((int)1);
c.Abc(i);

les résultats sont BBCA. C'est parce que dans le cas de la classe B, le compilateur sait qu'il peut implicitement exprimés tout en int en double. Dans le cas de la classe C, le compilateur sait qu'il peut lancer le littéral int 1 à un octet (car la valeur 1 correspond à un octet) donc C de la méthode Abc est utilisé. Le compilateur, cependant, ne peut pas implicitement jeter un vieux int à un octet, donc, c.Abc(i) ne pouvez pas utiliser C de la méthode Abc. Il faut utiliser la classe parent dans ce cas.

Cette page sur l'Implicite Conversions Numériques, montre une table compacte dont les types numériques ont conversions implicites à d'autres types numériques.

12voto

Rob Points 2095

Vous obtenez les mêmes fonctionnalités, même lorsque vous définissez B comme:

class B : A
{
    public void Abc(object p)
    {
        Console.Write("B");
    }
}

C'est tout simplement parce que la résolution de surcharge se fait en regardant les méthodes définies dans la classe actuelle. S'il y a des méthodes appropriées, dans le courant de la classe, il s'arrête à la recherche. Seulement si il y a pas de matchs qu'il a l'air à la base des classes

Vous pouvez prendre un coup d'oeil à la résolution de Surcharge spec pour une explication détaillée.

7voto

Jirka Hanika Points 8266

Différents langages (comme C++, Java ou C#) sont très différents de résolution de surcharge règles. En C#, la surcharge a été correctement choisi par le langage de spécification. Si vous vouliez que les autres surcharge pour être choisi, vous avez le choix. Rappelez-vous ceci:

Lorsqu'une classe dérivée a l'intention de déclarer une autre surcharge d'une méthode héritée, de manière à traiter tous disponibles surcharges que l'égalité des droits de ses pairs, il doit aussi explicitement remplacer toutes les hérité des surcharges avec une base à l'appeler ainsi.

Qu'est-ce que la langue de conception de bénéficier d'exiger cet exercice?

Imaginez que vous êtes à l'aide d'un 3ème partie de la bibliothèque (par exemple, .NET framework) et découlant de l'une de ses classes. À un certain point vous présenter une méthode privée appelés Abc (un nouveau nom unique, pas de surcharge de quoi que ce soit). Deux ans plus tard, la mise à niveau de la 3ème partie de la version de bibliothèque sans se rendre compte qu'ils ont aussi ajouté une méthode, accessible à vous et appelé, malheureusement, Abc, sauf qu'il a un autre type de paramètre quelque part (si la mise à niveau n'est pas de vous alerter avec une erreur de compilation) et se comporte de manière subtilement différente ou peut-être même a un but différent totalement. Voulez-vous vraiment à la moitié de vos appels privés d' Abc silencieuse redirigé vers la 3ème partie Abc? En Java, cela peut arriver. En C# ou C++, ce n'est pas qui va se passer.

La hausse de la C# est qu'il est un peu plus facile, pour un redistribué de la bibliothèque, pour ajouter des fonctionnalités rigoureusement en gardant la compatibilité descendante. De deux façons en fait:

  • Vous n'aurez plus jamais salir avec vos clients privés des appels de méthode à l'intérieur de leur propre code.
  • Vous ne brisera jamais vos clients par l'ajout d'un nouveau nom unique méthode, même si tu dois encore réfléchir à deux fois avant d'ajouter une surcharge de VOTRE méthode existante.

Revers de la médaille, C# est qu'il coupe un trou dans la programmation orientée objet de la philosophie de la redéfinition des méthodes toujours changeant seulement la mise en œuvre, mais pas l'API de la classe.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X