Otros ya han señalado que hay un número infinito de posibles tipos de delegados que podría haber significado; ¿Qué tiene de especial el Func
que merece ser el valor predeterminado en lugar de Predicate
o Action
o cualquier otra posibilidad? Y, para lambdas, ¿por qué es obvio que la intención es elegir el formulario de delegado, en lugar de la forma de árbol de expresión?
Pero podríamos decir que Func
es especial, y que el tipo inferido de un método lambda o anónimo es Func de algo. Todavía tendríamos todo tipo de problemas. ¿Qué tipos te gustaría inferir para los siguientes casos?
var x1 = (ref int y)=>123;
No hay ningún tipo de código Func<T>
que realice una referencia.
var x2 = y=>123;
No conocemos el tipo del parámetro formal, aunque sí sabemos el retorno. (O ¿verdad? Es el retorno int? Tiempo? Corto? Bytes?)
var x3 = (int y)=>null;
No sabemos el tipo de retorno, pero no podemos estar vacío. El tipo de devolución podría ser cualquier tipo de referencia o cualquier tipo de valor que admite valores.
var x4 = (int y)=>{ throw new Exception(); }
Una vez más, no sabemos el tipo de retorno, y esta vez podemos anuladas.
var x5 = (int y)=> q += y;
¿Está destinado a ser una declaración de devolución de vacío lambda o algo que devuelve el valor asignado a q? Ambos son legales; ¿Qué deberíamos elegir?
Ahora, puede decir, bueno, simplemente no admite ninguna de esas características. Solo soporte casos "normales" donde los tipos se pueden resolver. Eso no ayuda. ¿Cómo eso me hace la vida más fácil? Si la función funciona a veces y falla a veces, entonces todavía tengo que escribir el código en detectar todas esas situaciones de falla y dar un mensaje de error significativo para cada uno. Todavía tenemos que especificar todo ese comportamiento, documentarlo, escribir pruebas para él, etc. Esta es una característica muy costosa que le ahorra al usuario una media docena de pulsaciones de teclas.Tenemos mejores formas de agregar valor al lenguaje que pasar mucho tiempo escribiendo casos de prueba para una función que no funciona la mitad del tiempo y que no proporciona casi ningún beneficio en los casos en que funciona.
La situación en la que es realmente útil es:
var xAnon = (int y)=>new { Y = y };
porque no hay ningún tipo de "decible" para esa cosa. Pero tenemos este problema todo el tiempo, y sólo tiene que utilizar el método de la inferencia para deducir el tipo:
Func<A, R> WorkItOut<A, R>(Func<A, R> f) { return f; }
...
var xAnon = WorkItOut((int y)=>new { Y = y });
y ahora trabaja tipo de método de inferencia qué tipo func es.
Nota sobre su argumento * 4 arguments *, en .NET 4, 'Func <>' acepta hasta 16 argumentos. –
Gracias por la aclaración. Estoy usando .NET 3.5. – Marlon
¿Por qué haría el compilador pensar que es un 'Func'? ¡Parece un 'Converter ' para mí! –