Est-ce un bug?
Oui.
Félicitations, vous avez trouvé un bogue dans la résolution des surcharges. Le bogue se reproduit en C # 4 et 5; il ne se reproduit pas dans la version "Roslyn" de l'analyseur sémantique. J'ai informé l'équipe de test C # 5 et j'espère que nous pourrons faire enquête et résoudre ce problème avant la version finale. (Comme toujours, pas de promesses.)
Une analyse correcte suit. Les candidats sont:
0: C(params string[]) in its normal form
1: C(params string[]) in its expanded form
2: C<string>(string)
3: C(string, object)
Le candidat zéro est évidemment inapplicable car il string
n'est pas convertible en string[]
. Cela en laisse trois.
Des trois, nous devons déterminer une meilleure méthode unique. Nous faisons cela en comparant par paires les trois candidats restants. Il existe trois paires de ce type. Tous ont des listes de paramètres identiques une fois que nous supprimons les paramètres facultatifs omis, ce qui signifie que nous devons passer à la ronde de départage avancée décrite dans la section 7.5.3.2 de la spécification.
Quel est le meilleur, 1 ou 2? Le bris d'égalité pertinent est qu'une méthode générique est toujours pire qu'une méthode non générique. 2 est pire que 1. Donc 2 ne peut pas être le gagnant.
Quel est le meilleur, 1 ou 3? Le bris d'égalité pertinent est: une méthode applicable uniquement sous sa forme développée est toujours pire qu'une méthode applicable sous sa forme normale. Donc 1 est pire que 3. Donc 1 ne peut pas être le gagnant.
Quel est le meilleur, 2 ou 3? Le bris d'égalité pertinent est qu'une méthode générique est toujours pire qu'une méthode non générique. 2 est pire que 3. Donc 2 ne peut pas être le gagnant.
Pour être choisi parmi un ensemble de plusieurs candidats applicables, un candidat doit être (1) invaincu, (2) battre au moins un autre candidat et (3) être le candidat unique qui possède les deux premières propriétés. Le troisième candidat n'est battu par aucun autre candidat et bat au moins un autre candidat; c'est le seul candidat avec cette propriété. Par conséquent, le troisième candidat est le meilleur candidat unique . Cela devrait gagner.
Non seulement le compilateur C # 4 se trompe-t-il, mais comme vous le notez correctement, il signale un message d'erreur bizarre. Le fait que le compilateur n'obtienne pas l'analyse de résolution de surcharge est un peu surprenant. Il n'est absolument pas surprenant qu'il obtienne le message d'erreur incorrect; l'heuristique d'erreur de "méthode ambiguë" choisit essentiellement deux méthodes quelconques de l'ensemble candidat si une meilleure méthode ne peut être déterminée. Il n'est pas très bon pour trouver la «vraie» ambiguïté, s'il y en a une.
On pourrait raisonnablement se demander pourquoi. Il est assez délicat de trouver deux méthodes qui soient "sans ambiguïté" car la relation "de bêtise" est intransitive . Il est possible de trouver des situations où le candidat 1 est meilleur que 2, 2 est meilleur que 3 et 3 est meilleur que 1. Dans de telles situations, nous ne pouvons pas faire mieux que d'en choisir deux comme "ambigus".
Je voudrais améliorer cette heuristique pour Roslyn mais c'est une faible priorité.
(Exercice pour le lecteur: "Concevoir un algorithme de temps linéaire pour identifier le meilleur membre unique d'un ensemble de n éléments où la relation d'amertume est intransitive" était l'une des questions qui m'ont été posées le jour où j'ai interviewé pour cette équipe. Ce n'est pas un algorithme très difficile; essayez-le.)
L'une des raisons pour lesquelles nous avons repoussé l'ajout d'arguments facultatifs à C # pendant si longtemps était le nombre de situations ambiguës complexes qu'il introduit dans l'algorithme de résolution de surcharge; apparemment, nous n'avons pas fait les choses correctement.
Si vous souhaitez saisir un problème Connect pour le suivre, n'hésitez pas. Si vous voulez simplement que cela soit porté à notre attention, considérez-le comme fait. Je ferai un suivi avec des tests l'année prochaine.
Merci d'avoir porté ceci à mon attention. Toutes mes excuses pour l'erreur.
'Overloaded.ComplexOverloadResolution(string)'
réfère à la<string>(string)
méthode; Je pense que cela fait référence à la(string, object)
méthode sans objet fourni.