¿Es esto un error?
Si.
Felicitaciones, ha encontrado un error en la resolución de sobrecarga. El error se reproduce en C # 4 y 5; no se reproduce en la versión "Roslyn" del analizador semántico. He informado al equipo de prueba de C # 5 y espero que podamos investigar y resolver esto antes del lanzamiento final. (Como siempre, sin promesas).
Sigue un análisis correcto. Los candidatos son:
0: C(params string[]) in its normal form
1: C(params string[]) in its expanded form
2: C<string>(string)
3: C(string, object)
El candidato cero es obviamente inaplicable porque string
no es convertible a string[]
. Eso deja tres.
De los tres, debemos determinar el mejor método único. Lo hacemos haciendo comparaciones por pares de los tres candidatos restantes. Hay tres pares de este tipo. Todos ellos tienen listas de parámetros idénticas una vez que eliminamos los parámetros opcionales omitidos, lo que significa que tenemos que pasar a la ronda avanzada de desempate descrita en la sección 7.5.3.2 de la especificación.
¿Qué es mejor, 1 o 2? El desempate relevante es que un método genérico siempre es peor que un método no genérico. 2 es peor que 1. Así que 2 no puede ser el ganador.
¿Cuál es mejor, 1 o 3? El desempate relevante es: un método aplicable solo en su forma expandida es siempre peor que un método aplicable en su forma normal. Por tanto, 1 es peor que 3. Por tanto, 1 no puede ser el ganador.
¿Qué es mejor, 2 o 3? El desempate relevante es que un método genérico siempre es peor que un método no genérico. 2 es peor que 3. Así que 2 no puede ser el ganador.
Para ser elegido de un conjunto de múltiples candidatos aplicables, un candidato debe estar (1) invicto, (2) vencer al menos a otro candidato y (3) ser el candidato único que tiene las dos primeras propiedades. El candidato tres no es derrotado por ningún otro candidato y gana al menos a otro candidato; es el único candidato con esta propiedad. Por lo tanto, el candidato tres es el mejor candidato único . Debería ganar.
El compilador de C # 4 no solo se equivoca, sino que también notó correctamente que está informando un extraño mensaje de error. Que el compilador esté haciendo mal el análisis de resolución de sobrecarga es un poco sorprendente. Que el mensaje de error sea incorrecto no es ninguna sorpresa; la heurística de error del "método ambiguo" básicamente elige dos métodos del conjunto de candidatos si no se puede determinar el mejor método. No es muy bueno para encontrar la ambigüedad "real", si es que la hay.
Uno podría preguntarse razonablemente por qué es así. Es bastante complicado encontrar dos métodos que sean "inequívocamente ambiguos" porque la relación de "mejoría" es intransitiva . Es posible llegar a situaciones en las que el candidato 1 es mejor que 2, 2 es mejor que 3 y 3 es mejor que 1. En tales situaciones, no podemos hacer nada mejor que elegir dos de ellos como "los ambiguos".
Me gustaría mejorar esta heurística para Roslyn pero es una prioridad baja.
(Ejercicio para el lector: "Diseñar un algoritmo de tiempo lineal para identificar el mejor miembro único de un conjunto de n elementos donde la relación de mejora es intransitiva" fue una de las preguntas que me hicieron el día que me entrevisté para este equipo. No es un algoritmo muy difícil; pruébalo.)
Una de las razones por las que rechazamos la adición de argumentos opcionales a C # durante tanto tiempo fue la cantidad de situaciones ambiguas complejas que introduce en el algoritmo de resolución de sobrecarga; aparentemente no lo hicimos bien.
Si desea ingresar un problema de Connect para rastrearlo, no dude. Si solo quiere que nos lo notifique, considérelo hecho. Seguiré con las pruebas el próximo año.
Gracias por informarme sobre esto. Disculpas por el error.
'Overloaded.ComplexOverloadResolution(string)'
refiera al<string>(string)
método; Creo que se refiere al(string, object)
método sin objeto proporcionado.