Prefacio: Pase a la edición si quiere la explicación completa. Spoiler: Los métodos de extensión son un truco de compilación, y en realidad tienen un argumento más de lo que parecen cuando los invocas.
Está en la resolución del grupo de métodos. Aparentemente, el compilador de C# no se toma el tiempo para determinar si el método que está utilizando tiene sobrecargas o no; solo siempre requiere un lanzamiento explícito. Salida:
What is a method group in C#?
Method Inference does not work with method group
El grupo método que regresa de reader.GetDoubleOrNull
se estrecha por lo que intenta convertir a: GetDoubleOrNull
podría referirse a cualquier número de métodos sobrecargados con ese nombre. Debes lanzarlo explícitamente.
Curiosamente, ni siquiera se puede asignar un grupo de método a una variable de tipo implícitamente por la misma razón:
var x = reader.GetDoubleOrNull;
falla al compilar, ya que requiere una conversión explícita.
Editar estoy bastante seguro de que la confusión en este punto tiene que ver con los métodos de extensión:
Mira la siguiente clase de prueba:
public static class Extensions
{
public static List<T> GetList<T>(this IDataReader reader, Func<string, T> del)
{
throw new NotImplementedException();
}
public static double? GetDoubleOrNull(this IDataReader reader, string columnName)
{
throw new NotImplementedException();
}
public static double? blah(this string s)
{
throw new NotImplementedException();
}
}
Se puede llamar con éxito
var x = reader.GetList(Extensions.blah);
¿Por qué podría ser? blah
es también un método de extensión estático, por lo tanto, según su evidencia, parecería que la línea anterior no debe compilarse. Para complicar aún más las cosas, vamos a añadir este método:
public static List<T> GetList2<T>(this IDataReader reader, Func<IDataReader, string, T> del)
{
throw new NotImplementedException();
}
Ahora puede llamar
x = reader.GetList2(Extensions.GetDoubleOrNull);
y se compilará correctamente. ¿Lo que da?
Aquí está la respuesta: Los métodos de extensión no realmente agregan métodos a sus objetos. Son realmente un truco de compilación para permitirle programar como si esos métodos fueran parte de sus clases. De here:
En su código se invoca el método de extensión con el método de instancia sintaxis . Sin embargo, el lenguaje intermedio (IL) generado por el compilador traduce su código en una llamada en el método estático. Por lo tanto, el principio de encapsulación no se está violando realmente . De hecho, los métodos de extensión no pueden acceder a las variables privadas en el tipo que se están extendiendo.
Por lo tanto, cuando se llama
var x = reader.GetDoubleOrNull("myColumnName");
lo que realmente se compila y se ejecuta es esencialmente esto (una llamada perfectamente legítimo, aunque es un método de extensión):
var x = Extensions.GetDoubleOrNull(reader, "myColumnName");
Así , cuando intente utilizar GetDoubleOrNull
como arg para Func<string, double?>
, el compilador indica "Puedo convertir GetDoubleOrNull
en Func<IDataReader, string, double?>
porque tiene dos argumentos, pero no k ahora la forma de convertirlo en un Func<string, double?>
"
A pesar de que está llamando como si se trata de un método de instancia de la IDataReader
con una arg, no es: esto es sólo un método estático con dos argumentos que el C# el compilador te ha engañado para que pienses que es parte de IDataReader
.
Muy interesante. Un lanzamiento explícito '' var x = reader.GetList ((Func) Lector.GetDoubleOrNull) '' también funciona. Resharper marca el lanzamiento como redundante, pero sin él la compilación falla. ¿Está Jon Skeet cerca? –
¿Hay alguna manera de invocar a Jon Skeet (o tal vez a Eric Lippert)? ¿Dicen su nombre tres veces o algo así? – Chris
relacionado: http://stackoverflow.com/questions/7745852/method-inference-does-not-work-with-method-group y http://stackoverflow.com/questions/2057146/compiler-ambiguous-invocation-error -anonymous-method-and-method-group-with-fun – AakashM