Impossibile inizializzare LambdaExpression con un'espressione

c# expression-trees lambda

Domanda

Domanda simile a quella di John K , ma più specifica e la risposta accettata non soddisfa i miei bisogni.

Questo compila bene:

Expression<Func<object, object>> specificExpression = (object o) => new object();
Expression generalExpression = specificExpression;

E questo non lo fa:

Expression generalExpression = (object o) => new object();

Errore di compilazione segnalato:

Cannot convert lambda expression to type 'System.Linq.Expressions.Expression' because it is not a delegate type

Expression<Func<T1,T2>> deriva da Expression .

Ora ho un framework con metodi che accettano tutti i tipi di espressioni, ad esempio type Expression . Essere costretti a lanciare in modo esplicito lambda sulla corrispondente Expression<Func<T1,T2>> su ogni chiamata di metodo è frustrante.

Qualche buona ragione per cui questo comportamento OOP di base è rotto in questo caso?

Risposta accettata

La conversione non funziona perché il compilatore non può dedurre quale specifico tipo di espressione stai cercando di creare. E se lo facessi?

Expression generalExpression = (object o) => "foo";

Dovrebbe essere Expression<Func<object, string>> ? Che dire Expression<Func<object, object>> o Expression<Func<object, IComparable>> ? Questi tipi sarebbero tutti un tipo finale valido per l'albero delle espressioni e il compilatore non pretende di sapere cosa stai cercando di fare.

È necessario eseguire il cast attraverso il tipo specifico per informare il compilatore sul tipo di espressione che si desidera produrre:

Expression generalExpression = (Expression<Func<object, object>>)
    (object o) => new object();

Vedresti un errore simile nel compilatore se hai provato questo:

Delegate generalDelegate = delegate() { };

Si tratta di Action , o di un ThreadStart o di un altro tipo di delegato non valido per la restituzione di nullità?


Risposta popolare

Il compilatore C # valuta l'espressione sulla forma meno complessa, ad esempio:

 var x = (object o) => new object();

x dovrebbe essere un Func<object, object> , non Expression<Func<object, object>> . In questo caso, il compilatore sta determinando che il valore è un delegato e poiché Expression non può assumere un delegato (solo i tipi Expression<Func<>> / Expression<Action> possono), viene generato l'errore del compilatore.

Inoltre, vedi la risposta di @Riana, perché il modulo di espressione è actuall riscritto dal compilatore.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché