Supongamos que tengo una clase:¿Por qué los argumentos de expresión lambda son ambiguos entre Func y Expresión <Func>?
class MyClass {
public int MyMethod(Func<int, int> f) { return 0; }
public int MyMethod(Expression<Func<int, int>> f) { return 1; }
}
Cuando intento llamar al método con una expresión lambda, me sale un error de compilación que indica que la llamada es ambigua entre las dos sobrecargas:
var myClass = new MyClass();
myClass.MyMethod(x => 1 + x); // Error!
mientras que, por supuesto, llamar con un tipo explícito funciona bien:
myClass.MyMethod((Func<int, int>)(x => 1 + x)); // OK, returns 0
myClass.MyMethod((Expression<Func<int, int>>)(x => 1 + x)); // OK, returns 1
el árbol de expresión contiene más información (el código real), y puede wa nt para hacer uso de esta información cuando esté disponible. Pero también quiero que mi código funcione con los delegados. Desafortunadamente, esta ambigüedad lo hace así que tengo que encontrar otra manera de distinguir entre las dos llamadas, lo que arruina una API que de otro modo estaría limpia.
La especificación de C# no dice nada acerca de esta situación específica, por lo que en este sentido el comportamiento coincide con la especificación.
Sin embargo, hay un argumento para hacer que el árbol de expresiones se prefiera sobre el delegado. El método Compile
actúa como una conversión explícita de un árbol de expresiones a un delegado. El árbol de expresiones contiene más información, y cuando compila a un delegado, pierde esa información. No hay conversión en la otra dirección.
¿Hay alguna razón para no preferir el árbol de expresiones?
El argumento a favor de 'Func' es que puede ejecutarlo directamente sin tener que pasar por una etapa de compilación relativamente costosa. – Lee