2009-10-30 18 views

risposta

17

La prima sarà tradotto in:

objectList.Where(o => o.value1 < 100).Where(o=> o.value2 > 10) 

mentre il secondo sarà tradotto in:

objectList.Where(o => o.value1 < 100 && o.value2 > 10) 

Così, nel primo, si avrà una prima sequenza filtrata che viene nuovamente filtrato (la prima sequenza contiene tutti gli oggetti con valore < 100, la seconda contiene tutti gli oggetti con valore> 10 dalla prima sequenza), mentre la seconda esegue gli stessi confronti nella stessa espressione labda. Questo è valido da Linq agli oggetti, per altri fornitori dipende da come l'espressione è tradotta.

+1

In realtà è abbastanza impreciso. Se ispezionerai le fonti di 'Linq' vedrai che' Where' ha un metodo che traduce '.Where (x) .Where (y)' in '.Where (x && y)'. [fonte] (http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,f7e72dc9c9621f30) –

+0

Buon punto, non sono in grado di dire se l'ho verificato nel 2009 o se fosse stato vero tutto il tempo. – Philippe

1

Al livello base, si ottengono due operazioni Where anziché una. L'uso di Reflector è il modo migliore per esaminare ciò che viene fuori dall'altra estremità di un'espressione di query.

Sia che vengano ottimizzati per la stessa cosa dipende dal provider LINQ attuale: è necessario prendere l'intero albero e convertirlo in un'altra sintassi. Per LINQ To Objects, non è così.

C# in Depth è buono per darvi una comprensione di questo argomento.

6

Il primo si traduce in:

objectList.Where(o => o.value1 < 100) 
      .Where(o => o.value2 > 10); 

mentre il secondo si ottiene:

objectList.Where(o => o.value1 < 100 && o.value2 > 10);  

E 'functionnaly la stessa, e mentre la seconda avrebbe risparmiato una chiamata di metodo, la differenza di prestazioni è trascurabile. Usa ciò che è più leggibile per te.

Cioè, se si sta usando linq agli oggetti. Se si sta utilizzando un provider, dipende da come è implementato (se il predicato non viene preso in considerazione nella query risultante, il risultato può essere non ottimale).

+0

In realtà l'ho digitato direttamente. Hai ragione, il selettore di identità non ha senso. –

0

Che ne dici di una risposta: con & & non puoi garantire che entrambe le espressioni siano valutate (se la prima condizione è falsa allora la seconda potrebbe non essere valutata). Con le due clausole in cui puoi, allora. Non ho idea se sia vero ma suona bene per me!

+2

Non penso sia vero. Se si tratta di Linq to Objects, la prima chiamata Where restituirà un'enumerazione contenente solo gli elementi in cui la condizione 1 è vera. Quindi la condizione 2 verrà chiamata solo per questi articoli. – Niki

+0

Giusto, ma non è vero il contrario? Supponiamo che tu usi un semplice '&', quindi entrambi verranno valutati nel secondo caso. Ad ogni modo, meglio evitare di usare effetti collaterali in questi :) – Philippe

0

A parità di altre condizioni, sceglierei la versione condition1 && condition2, per motivi di leggibilità del codice.

3

Ho appena il profilo. Nessuna differenza nel codice SQL

+0

Supponendo che l'OP stia parlando di LINQ to SQL. =) –

6

La risposta contrassegnata lo rende un po 'impreciso.

Come detto @Philippe, il primo sarà tradotto in:

objectList.Where(o => o.value1 < 100).Where(o=> o.value2 > 10) 

mentre il secondo sarà tradotto in:

objectList.Where(o => o.value1 < 100 && o.value2 > 10) 

MaLinq ha una poca ottimizzazione per le chiamate con catena Where.

Se si controlla Linq's codice sorgente verrà visualizzato il seguente:

class WhereEnumerableIterator<TSource> : Iterator<TSource> 
{ 
    public override IEnumerable<TSource> Where(Func<TSource, bool> predicate) 
    { 
     return new WhereEnumerableIterator<TSource>(source, 
      CombinePredicates(this.predicate, predicate)); 
    } 
} 

Cosa CombinePredicates non c'è sta combinando i due predicati con && tra di loro:

static Func<TSource, bool> CombinePredicates<TSource>(Func<TSource, bool> predicate1, 
    Func<TSource, bool> predicate2) 
{ 
    return x => predicate1(x) && predicate2(x); 
} 

Quindi objectList.Where(X).Where(Y) equivale a objectList.Where(X && Y) fatta eccezione per il tempo di creazione della query (che è comunque estremamente breve) e l'invocazione di due predicati.

linea di fondo è che esso non filtro o iterare la raccolta due volte - ma una volta composito.

Problemi correlati