IEnumerable<T>rappresenta un cursore solo in avanti di T. .NET 3.5 ha aggiunto metodi di estensione che includevano LINQ standard query operatorssimili Wheree First, con qualsiasi operatore che richieda predicati o funzioni anonime Func<T>.
IQueryable<T>implementa gli stessi operatori di query standard LINQ, ma accetta Expression<Func<T>>predicati e funzioni anonime. Expression<T>è un albero delle espressioni compilato, una versione suddivisa del metodo ("metà compilato" se lo si desidera) che può essere analizzata dal provider dell'interrogabile e utilizzata di conseguenza.
Per esempio:
IEnumerable<Person> people = GetEnumerablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();
IQueryable<Person> people = GetQueryablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();
Nel primo blocco, x => x.Age > 18è un metodo anonimo ( Func<Person, bool>), che può essere eseguito come qualsiasi altro metodo. Enumerable.Whereeseguirà il metodo una volta per ogni persona, yieldinserendo i valori per i quali il metodo ha restituito true.
Nel secondo blocco, x => x.Age > 18c'è un albero delle espressioni ( Expression<Func<Person, bool>>), che può essere pensato come "è la proprietà 'Età'> 18".
Ciò consente l'esistenza di elementi come LINQ-to-SQL perché possono analizzare l'albero delle espressioni e convertirlo in SQL equivalente. E poiché il provider non deve eseguire fino a quando non IQueryableviene elencato (implementa IEnumerable<T>, dopotutto), può combinare più operatori di query (nell'esempio sopra Wheree FirstOrDefault) per fare scelte più intelligenti su come eseguire l'intera query rispetto ai dati sottostanti sorgente (come usare SELECT TOP 1in SQL).
Vedere: