2011-10-12 9 views
11

Considéresemétodo de inferencia no funciona con grupo método

void Main() 
{ 
    var list = new[] {"1", "2", "3"}; 
    list.Sum(GetValue); //error CS0121 
    list.Sum(s => GetValue(s)); //works ! 
} 

double GetValue(string s) 
{ 
    double val; 
    double.TryParse(s, out val); 
    return val; 
} 

La descripción para el error CS0121 es

La llamada es ambigua entre los métodos o propiedades siguientes: 'System.Linq.Enumerable.Sum<string>(System.Collections.Generic.IEnumerable<string>, System.Func<string,decimal>)' y 'System.Linq.Enumerable.Sum<string>(System.Collections.Generic.IEnumerable<string>, System.Func<string,decimal?>)'

Lo que no entiendo es, qué en formación hace s => GetValue(s) dar el compilador que simplemente GetValue no - ¿no es el último azúcar sintáctica para el primero?

Respuesta

18

La respuesta de Mark es correcta pero podría necesitar un poco más de explicación.

El problema es, de hecho, debido a una sutil diferencia entre cómo se manejan los grupos de métodos y cómo se manejan las lambdas.

En concreto, la sutil diferencia es que un grupo método se considera que es convertible en un tipo de delegado únicamente sobre la base de si los argumentos partido, no también sobre la base de si el tipo retorno partidos. Lambdas comprueba los argumentos y el tipo de devolución.

El motivo de esta extraña regla es que las conversiones de grupo de métodos a delegados son esencialmente una solución del problema de resolución de sobrecarga. Supongamos que D es el tipo de delegado double D(string s) y M es un grupo de métodos que contiene un método que toma una cadena y devuelve una cadena. Al resolver el significado de una conversión de M a D, sobrecargamos la resolución como si dijéramos M (cadena). La resolución de sobrecarga escogerá la M que toma una cadena y devuelve una cadena, por lo que M es convertible a ese tipo de delegado , aunque la conversión dará como resultado un error posterior. Así como la resolución de sobrecarga "normal" tendría éxito si dijera "cadena s = M (nulo);" - la resolución de sobrecarga tiene éxito, aunque eso cause una falla de conversión más adelante.

Esta regla es sutil y un poco rara. El resultado aquí es que su grupo de métodos es convertible a todos los tipos de delegados diferentes que son los segundos argumentos de cada versión de Sum que toma un delegado. Como no se puede encontrar la mejor conversión, la resolución de sobrecarga en el grupo de métodos Sum es ambigua.

grupo Método reglas conversiones son plausibles, pero un poco extraño en C#. Me molesta un poco que no sean consistentes con las conversiones lambda más "intuitivamente correctas".

+0

Si tuviera una máquina del tiempo, ¿cómo los cambiaría? ¿Harías que consideren los tipos de devolución, como lambdas?¿O harías un cambio sutil diferente? – configurator

+0

¡Interesante! Jugué con él en LinqPad y, de hecho, incluso si tengo 'double D1 (string s)' y 'int D1 (string s)', un grupo de métodos con una firma de 'string M (string)' produciría un ambiguo error de llamada, incluso aunque ambas firmas no se ajusten de todos modos. Esto a diferencia de un lambda, que probaría todos y le dará un error de conversión en el último (¿el primero?) Que intenta. –

+0

Sin embargo, si no hay un problema de resolución de sobrecarga (y se utiliza la firma incorrecta), el error de grupo de método ("M tiene el tipo de devolución incorrecto") es ligeramente más informativo que el de lambda ("No se puede convertir implícitamente el tipo 'cadena' a 'doble'") –

8

s => GetValue(s) es una expresión lambda y GetValue es un grupo de métodos, que es algo completamente diferente. Ambos pueden considerarse azúcar sintáctico para new Func<string,double>(...) pero la única forma en que se relacionan entre sí es que la expresión lambda incluye una llamada al GetValue(). Cuando se trata de convertir a un delegado, los grupos de métodos tienen diferentes reglas de conversión que las expresiones lambda con respecto a los tipos de devolución. Ver Why is Func<T> ambiguous with Func<IEnumerable<T>>? y Overloaded method-group argument confuses overload resolution?.

+0

Interesante (upvoted) - echa un vistazo a los enlaces –

Cuestiones relacionadas