2010-06-07 13 views
16

In una recente intervista mi è stato chiesto quale fosse la differenza tra .Any() e .Length > 0 e perché avrei usato entrambi durante il test per vedere se una raccolta avesse elementi.Domanda di intervista: .Any() vs if (.Length> 0) per verificare se una raccolta ha elementi

Questo mi ha gettato un po 'come sembra un po' ovvio, ma sento che potrebbe mancare qualcosa.

Ho suggerito di utilizzare .Length quando è semplicemente necessario sapere che una raccolta contiene elementi e .Any() quando si desidera filtrare i risultati.

Presumibilmente .Any() prende un colpo di prestazioni troppo come deve fare un ciclo/query internamente.

+0

Solo curioso, era un'opzione '.Count()? Userà '.Length' (in realtà' .Count' dall'interfaccia 'ICollection') se disponibile, ed enumererà se non ...' .Any() 'non ha una scorciatoia come questa. –

+0

Ho sempre pensato che le proprietà native siano precalcolate se sono disponibili come '.length' per array e' .count' per la raccolta. Perciò userei '.any()' solo se hey non è disponibile o voglio un controllo '.any (lambda) 'condizionale. – Nope

risposta

22

Length esiste solo per alcuni tipi di raccolta come Array.

Any è un metodo di estensione che può essere utilizzato con qualsiasi raccolta che implementa IEnumerable<T>.

Se è presente Length, è possibile utilizzarlo, altrimenti utilizzare Any.


Presumibilmente .Any() prende un calo di prestazioni anche in quanto ha a che fare un loop/interrogazione internamente.

Enumerable.Any non loop. Recupera un iteratore e verifica se MoveNext restituisce true. Ecco il codice sorgente da .NET Reflector.

public static bool Any<TSource>(this IEnumerable<TSource> source) 
{ 
    if (source == null) 
    { 
     throw Error.ArgumentNull("source"); 
    } 
    using (IEnumerator<TSource> enumerator = source.GetEnumerator()) 
    { 
     if (enumerator.MoveNext()) 
     { 
      return true; 
     } 
    } 
    return false; 
} 
+0

C'è anche una versione 'IQueryable ', ma non sono ciò di cui l'OP sta parlando, forse entrambi. Modifica: per collezione sto supponendo che tu abbia ragione, solo linq-to-entities –

+0

Buona spiegazione grazie – Chris

1

Length è una struttura di tipi di matrice, mentre Any() è un metodo di estensione di Enumerable. Pertanto, è possibile utilizzare Length solo quando si lavora con gli array. Quando si lavora con più tipi astratti (IEnumerable<T>), è possibile utilizzare Qualsiasi().

0

Penso che questa sia una domanda più generale su cosa scegliere se abbiamo 2 modi per esprimere qualcosa. In questa situazione vorrei suggerire la frase: "Sii specifico" citazione da Peter Norvig nel suo libro PAIP

Essere specifici significa usare ciò che meglio descrive ciò che stai facendo. Così ciò che si vuole dire è qualcosa di simile:

collection.isEmpty() 

Se non si dispone di tale costrutto La scelta del linguaggio comune che le comunità usati. Per me .Length > 0 non è il migliore dal momento che impone che è possibile ridimensionare l'oggetto. Supponi che la tua lista infinita dell'attrezzo. .Lenght ovviamente non funzionerebbe.

1

. Lunghezza ... Sistema.Array . Qualsiasi ... IEnumerable (metodo di estensione).

Preferisco utilizzare "lunghezza" ogni volta che riesco a trovarlo. La proprietà è comunque leggera rispetto a qualsiasi chiamata di metodo.

Tuttavia, l'implementazione di "Qualsiasi" non farà altro che il codice riportato di seguito.

private static bool Any<T>(this IEnumerable<T> items) 
     { 
      return items!=null && items.GetEnumerator().MoveNext(); 
     } 

Inoltre, Una domanda migliore avrebbe potuto essere una differenza beterrn "Count" e ".Length", cosa dire :).

+0

Interessante ... puoi spiegare: "La proprietà è comunque leggera rispetto a qualsiasi chiamata di metodo." –

+0

@David: Property è generalmente un get/set su un campo (un valore in memoria) mentre un metodo ha la libertà di eseguire tutti i calcoli possibili. Mi affiderei sempre a una chiamata a get_Property piuttosto che a una chiamata di metodo. (ad es .: obj.ComputedValue Vs ComputeValue()) –

+1

Quindi è solo la convenzione o le linee guida, non una ragione tecnica. Una proprietà potrebbe essere implementata in violazione della convenzione (ad esempio, la proprietà potrebbe chiamare il metodo). –

0

suona abbastanza simile a questa domanda StackOverflow su differenza tra Count e .Any per la verifica dell'esistenza di un risultato: Check for Existence of a Result in Linq-to-xml

In questo caso è meglio utilizzare Any poi contare, come Conte itererà tutti gli elementi di un IEnumerable

+1

Questo non è vero, '.Count()' ** usa ** la proprietà '.Count' (che ottiene' .Length' su una Array ad esempio) su 'ICollection' (generico o no),'. Any() '** non lo userà e lo enumererà, puoi attivare reflector per vederlo, ancora vero in .Net 4. Un' IQueryable 'è una storia diversa, ma su' IEnumerable ' non cambia. –

+0

Questo è interessante: ho interpretato quanto segue come Count che enumera e Any non lo farà: http://rapidapplicationdevelopment.blogspot.com/2009/07/ienumerablecount-is-code-smell.html –

+0

@Nick: ' Any() '(almeno il sovraccarico che non accetta argomenti) enumera più di * un * elemento. 'Conteggio()', se il sottostante 'IEnumerable ' non è un 'ICollection ', enumera '* tutti * gli elementi. Per questo motivo ha molto più senso usare 'Any()' di 'Count()> 0' se il tipo di raccolta non è noto. –

0

Sappiamo che .Length viene utilizzato solo per gli array e .Any() viene utilizzato per le raccolte di IEnumerable.

È possibile scambiare Count per .Length e si ha la stessa domanda per lavorare con le collezioni di IEnumberable

Sia .Any() e Count eseguire un controllo null prima di iniziare un enumeratore. Quindi per quanto riguarda le prestazioni sono uguali.

Per quanto riguarda la matrice lascia supporre abbiamo la seguente riga:

int[] foo = new int[10]; 

Qui foo.Length è 10. Anche se questo è corretto, non può essere la risposta alla tua ricerca, perché non abbiamo aggiunto nulla alla matrice ancora. Se pippo è nullo genererà un'eccezione.

12

Immagino che l'intervistatore abbia voluto chiedere di verificare Any() versus Count() > 0 (al contrario di Length > 0).

Fondamentalmente, ecco l'affare.

Any() tenterà in modo efficace di determinare se una raccolta contiene membri enumerando un singolo elemento. (C'è un sovraccarico per verificare un determinato criterio usando un Func<T, bool>, ma suppongo che l'intervistatore si riferisca alla versione di Any() che non accetta argomenti.) Questo lo rende O (1).

Count() controllerà un alloggio Length o Count (da un T[] o un ICollection o ICollection<T>) prima. Questo sarebbe generalmente O (1). Se ciò non è disponibile, tuttavia, conterrà gli elementi in una raccolta enumerando l'intera cosa. Questo sarebbe O (n).

Una proprietà Count o Length, se disponibile, sarebbe molto probabilmente O (1), proprio come Any(), e probabilmente un rendimento migliore in quanto richiederebbe alcuna enumerazione a tutti. Ma il metodo di estensione Count() non garantisce questo. Quindi a volte è O (1), a volte O (n).

Presumibilmente, se hai a che fare con un anonimo IEnumerable<T> e non si sa se implementa ICollection<T> o no, siete molto meglio usare Any() di Count() > 0 se la vostra intenzione è semplicemente quella di assicurare la raccolta non è vuoto.

-2

.Length itera attraverso la raccolta e restituisce il numero di elementi.Complessità è O(n)

.Any controlla se la raccolta ha almeno un elemento. La complessità è O(1).

+2

La proprietà Length è garantita per essere un'operazione O (1) quando disponibile.Il conteggio, d'altra parte, dipende dal tipo di raccolta (è O (1) per una lista). – Matthieu

Problemi correlati