2012-04-12 6 views
33

Utilizzando automapper, mi ha colpito un luogo in cui un argomento di nome avrebbe fatto in forma molto bene:Perché un albero di espressioni non può contenere una specifica argomento con nome?

.ForMember(s => s.MyProperty, opt => opt.MapFrom(s => BuildMyProperty(s, isAdvanced: false))) 

Ma il compilatore zittirmi:

Un albero di espressione non può contenere una specifica argomento denominato

così ho dovuto tornare a:

.ForMember(s => s.MyProperty, opt => opt.MapFrom(s => BuildMyProperty(s, false))) 

Qualcuno sa perché il compilatore non consente gli argomenti con nome in questa situazione?

risposta

25

Si consideri il seguente:

static int M() { Console.Write("M"); return 1; } 
static int N() { Console.Write("N"); return 2; } 
static int Q(int m, int n) { return m + n; } 
... 
Func<int> f =()=>Q(n : N(), m: M()); 
Expression<Func<int>> x =()=>Q(n : N(), m: M()); 
Func<int> fx = x.Compile(); 
Console.WriteLine(f()); 
Console.WriteLine(fx()); 

L'utente accetta Spero che le ultime due linee devono fare esattamente la stessa cosa, giusto? Quale è quello di stampare NM3.

Ora, quale richiamo della libreria ad albero delle espressioni si desidera che la conversione dell'albero delle espressioni venga generata per garantire ciò? Non ce ne sono! Pertanto ci troviamo di fronte alle seguenti scelte:

  1. Implementare la funzione nella libreria dell'albero delle espressioni. Aggiungi una trasformazione nel motore di abbassamento dell'albero dell'espressione che conserva l'ordine di esecuzione degli argomenti con nome. Implementare il codice nel metodo Compile che tiene conto dell'ordine di esecuzione.
  2. Effettuare x =()=>Q(n : N(), m: M()); effettivamente implementato come x =()=>Q(M(), N()); ed essere incompatibile con la versione di albero non di espressione.
  3. Non consentire argomenti con nome negli alberi di espressione. Implementa un messaggio di errore in questo senso.

(1) è bello, ma costoso. (2) è un non-starter; non possiamo in buona coscienza introdurre questo tipo di "gotcha". (3) è economico ma irritante.

Abbiamo scelto (3).

+0

Questo messaggio di errore che ritengo dovrebbe davvero essere documentato a questo effetto. In altre parole, la ricerca di msdn per la stringa esatta del messaggio di errore dovrebbe fornirci questo chiarimento. http://social.msdn.microsoft.com/Search/en-US?query=%22An%20expression%20tree%20may%20not%20contain%20a%20named%20argument%20specification%22&ac=8 – payo

+0

Questo è eccellente - grazie Eric. Fino ad ora non avevo mai dato un'occhiata alle differenze tra 'Expression <...>' e 'Func <...>'. Quando si dice che (1) sarebbe costoso, tuttavia, ciò significa in termini di costi di sviluppo o che sarebbe computazionalmente costoso? –

+1

@BrandonLinton: Sarebbe costoso sviluppare, testare, documentare e mantenere, in particolare se confrontato con il vantaggio molto piccolo che offre. Avremmo potuto scegliere di supportarlo all'inizio: dopo tutto, VB ha sempre avuto argomenti con nome per le chiamate al metodo, ma abbiamo scelto di non farlo. –