Supponiamo che io sono una classe:Perché gli argomenti di espressione lambda sono ambigui tra Func ed Expression <Func>?
class MyClass {
public int MyMethod(Func<int, int> f) { return 0; }
public int MyMethod(Expression<Func<int, int>> f) { return 1; }
}
Quando provo a chiamare il metodo con un'espressione lambda, ottengo un errore di compilazione che indica che la chiamata è ambiguo tra i due overload:
var myClass = new MyClass();
myClass.MyMethod(x => 1 + x); // Error!
mentre, ovviamente, chiamando con un tipo esplicito funziona bene:
myClass.MyMethod((Func<int, int>)(x => 1 + x)); // OK, returns 0
myClass.MyMethod((Expression<Func<int, int>>)(x => 1 + x)); // OK, returns 1
l'albero di espressione contiene ulteriori informazioni (il codice vero e proprio), e posso wa nt per utilizzare queste informazioni quando sono disponibili. Ma voglio anche che il mio codice funzioni con i delegati. Sfortunatamente, questa ambiguità lo rende così devo trovare un altro modo per distinguere tra le due chiamate, che incasina un'API altrimenti pulita.
La specifica C# non dice nulla su questa situazione specifica, quindi in questo senso il comportamento corrisponde alle specifiche.
Tuttavia, è necessario specificare che l'albero delle espressioni deve essere preferito al delegato. Il metodo Compile
funge da conversione esplicita da un albero di espressioni a un delegato. L'albero delle espressioni contiene più informazioni e quando si compila un delegato, si perdono tali informazioni. Non c'è conversione nell'altra direzione.
Ci sono motivi per non preferire l'albero delle espressioni?
L'argomento a favore di 'Func' è che è possibile eseguirlo direttamente senza dover passare attraverso una fase di compilazione relativamente costosa. – Lee