2013-06-04 14 views
6

Ho il seguente metodo che restituisce un IEnumerable di tipo T. L'implementazione del metodo non è importante, a parte lo yield return a carico lento il IEnumerable. Questo è necessario in quanto il risultato potrebbe avere milioni di oggetti.Controllare se IEnumerable ha QUALSIASI riga senza enumerazione sull'intero elenco

public IEnumerable<T> Parse() 
{ 
    foreach(...) 
    { 
     yield return parsedObject; 
    } 
} 

Problema:

ho la proprietà seguente, che può essere utilizzato per determinare se il IEnumerable avrà nessun articolo:

public bool HasItems 
{ 
    get 
    { 
     return Parse().Take(1).SingleOrDefault() != null; 
    } 
} 

C'è forse un modo migliore per fare questo ?

+1

Possibile duplicato di [Howto: Count gli elementi da un IEnumerable senza l'iterazione] (http: // StackOverflow .com/questions/168901/howto-count-the-items-from-a-ienumerablet-without-iterating) – drzaus

risposta

22

IEnumerable.Any() restituirà true se ci sono elementi nella sequenza e false se non ci sono elementi nella sequenza. Questo metodo non eseguirà l'iterazione dell'intera sequenza (solo un massimo di un elemento) poiché restituirà true se supera il primo elemento e false se non lo fa.

+0

Oh, non ho mai saputo di questo sovraccarico di "Any". Ma non dovrebbe anche iterare almeno una volta? – davenewza

+0

No, non itera. Il metodo Any restituirà true se supera il primo elemento. – Marcus

+3

Questo non è corretto. Comincia ad iterare l'enumerabile, tuttavia non itera l'intera cosa. – Uatec

1

Simile a un Howto: Count the items from a IEnumerable<T> without iterating?Enumerable è destinato a essere un pigro , lettura-forward "lista", e, come la meccanica quantistica l'atto di indagare altera il suo stato.

Sede conferma: https://dotnetfiddle.net/GPMVXH

var sideeffect = 0; 
    var enumerable = Enumerable.Range(1, 10).Select(i => { 
     // show how many times it happens 
     sideeffect++; 
     return i; 
    }); 

    // will 'enumerate' one item! 
    if(enumerable.Any()) Console.WriteLine("There are items in the list; sideeffect={0}", sideeffect); 

enumerable.Any() è il modo più pulito per controllare se ci sono voci nell'elenco. Potresti provare a trasmettere qualcosa di non pigro, ad esempio if(null != (list = enumerable as ICollection<T>) && list.Any()) return true.

Oppure, lo scenario può consentire utilizzando un Enumerator e fare un controllo preliminare prima di enumerare:

var e = enumerable.GetEnumerator(); 
// check first 
if(!e.MoveNext()) return; 
// do some stuff, then enumerate the list 
do { 
    actOn(e.Current); // do stuff with the current item 
} while(e.MoveNext()); // stop when we don't have anything else 
+0

E l'aggiornamento del violino con l'enumeratore mostra che il controllo preliminare, mentre continua a valutare l'enumerabile 1 volta (es. 'Sideeffect ++') non risulta in enumerazione _extra_: https://dotnetfiddle.net/no3WoH – drzaus