2011-03-01 10 views
8

preferisco utilizzare metodi di estensione per le operazioni di base di LINQ query: Where(), Select, ma per complessi Select(), SelectMany(), e soprattutto OrderBy().ThenBy() dichiarazioni trovo la sintassi di query di essere molto più leggibile e naturale.Linq estensione mix e la sintassi

Oggi mi sono trovato con la seguente query:

from c in _myObject.ObjectsParent.ParentsEnumerable 
        .Where(c => 
         c == anotherObject || c.Parent == anotherObject) 
from q in c.MyObjectsEnumerable 
orderby c.SortKey, q.Description 
select new { Item = q, Text = c.Description + " -> " + q.Description }; 

è pericoloso (per migliorare la leggibilità, manutenibilità, o qualsiasi altro motivo) per mescolare la sintassi di query e l'estensione?

Questo può essere molto soggettivo, se lo è, mi dispiace se non soddisfa i requisiti per una buona domanda soggettiva. Fammi sapere se posso migliorarlo!

risposta

6

È pericoloso (per la leggibilità, la manutenibilità o qualsiasi altro motivo) mescolare sintassi di query ed estensioni?

Il pericolo maggiore che potrei vedere è la potenziale aggiunta di "sorpresa" nel codice, specialmente se vista da altri sviluppatori.

Da un punto di vista della compilazione, la sintassi della query viene tradotta direttamente nelle chiamate al metodo di estensione, quindi qui non c'è necessariamente un problema tecnico. Tuttavia, questo potrebbe aggiungere nuove chiamate di metodo che, a prima vista, non sarebbero previste da molti sviluppatori. Questo potrebbe portare a un potenziale problema di manutenibilità.

Detto questo, se fatto con parsimonia e con una buona ragione, non sento che ci sia un vero problema nel mixare la sintassi. Questo è in realtà abbastanza comune - ad esempio, se si desidera scrivere nella sintassi della query, ma è necessario valutare completamente, è spesso racchiuso tra parentesi con .ToList() aggiunto - oppure se si desidera utilizzare PLINQ con la sintassi della query, è spesso from x in collection.AsParallel() , che tecnicamente sta anche mixando la sintassi ...

+0

Grazie, la risposta più diretta è stata la maggior parte dei miei pensieri e preoccupazioni. – Crisfole

3

Si potrebbe fare qualcosa di simile per rendere le cose un po 'più facili.

var firstQuery = _myObject.ObjectsParent.ParentsEnumerable 
       .Where(c => c == anotherObject || c.Parent == anotherObject); 

var secondQuery = from q in firstQuery.MyObjectsEnumerable 
        orderby firstQuery.SortKey, q.Description 
        select new { Item = q, 
           Text = firstQuery.Description + " -> " + q.Description }; 

Ora le query non sono mescolati

+1

La prima linea non è corretta ... si dovrebbe cadere la "dal c in" ... –

+0

Penso @ Reed-Copsey mean't (* non dovrebbe) perché firstQuery non ha la proprietà Descrizione solo un elemento di esso sarebbe. Quindi questo codice non funziona. – jbtule

1

uso i metodi di estensione, il mio collega utilizza la sintassi di query. Non c'è differenza.

Direi comunque che è necessario suddividere una query di grandi dimensioni in più piccoli per il debug e la leggibilità in quanto in genere non ci sono costi di tempo.

1

Avendo fatto ciò personalmente (anche se non per .Where, ma per .Cast) direi che dipende molto dai metodi di estensione che si stanno chiamando.

ad es. Mi sentivo perfettamente autorizzato a usare .Cast perché non era disponibile nello zucchero sintattico (AFAIK) ma probabilmente lo avrei evitato. Dov'è, perché questo ha una rappresentazione nella sintassi della query.

Detto questo, probabilmente utilizzerei. Selezionare per modificare anche i dati in una query ... Ma sono un po 'sadico.

3

Questo è un tipo di giudizio, ma molte domande tipo "best practice" tendono ad essere, almeno all'inizio. La mia opinione è che dovresti usare l'una o l'altra all'interno di una singola affermazione. Non proprio per alcun "pericolo" inerente alla miscelazione, ma per chiarezza.

In questo caso particolare, la clausola where è molto semplice e io la rifare in sintassi di query.

Ci sono tuttavia casi che non possono essere espressi elegantemente nella sintassi della query. Nei casi in cui è semplicemente inevitabile combinare le sintassi, le query potrebbero (ancora IMO) essere più leggibili se si divide la catena del metodo nella propria variabile, quindi si fa semplicemente riferimento a tale variabile nell'istruzione query-sintassi. Utilizzando la vostra come modello:

//The method chain can be pulled out as its own variable... 
var filteredParents = _myObject.ObjectsParent.ParentsEnumerable 
        .Where(c => c == anotherObject || c.Parent == anotherObject); 

//...which you can then substitute in a now purely query-syntax statement 
from c in filteredParents 
from q in c.MyObjectsEnumerable 
orderby c.SortKey, q.Description 
select new { Item = q, Text = c.Description + " -> " + q.Description }; 
2

non credo che sia pericoloso per mescolare, si pensano che dipende da ciò che è più leggibile, sintassi di query è molto leggibile, ma non come flexable, quindi mescolando del concatenamento sembra un piccolo prezzo da pagare. Immagino che la risposta sia se pensi che il seguente pienamente incatenato sia più leggibile di quello che hai scritto, personalmente penso che il tuo sia più facile da leggere.

_myObject.ObjectsParent 
      .ParentsEnumerable 
      .Where(c => c == anotherObject || c.Parent == anotherObject) 
      .SelectMany(c => c.MyObjectsEnumerable, (c, q) => new {c, q}) 
      .OrderBy(t => t.c.SortKey) 
      .ThenBy(t => t.q.Description) 
      .Select(t => new {Item = t.q, Text = t.c.Description + " -> " + t.q.Description}); 
Problemi correlati