2011-12-19 6 views
58

In C# uso LINQ e IEnumerable un bel po '. E tutto va bene-bene (o almeno per lo più così).C'è un singleton "Lista vuota" in C#?

Tuttavia, in molti casi, mi ritrovo che ho bisogno di uno IEnumerable<X> vuoto come predefinito. Cioè, mi piacerebbe

for (var x in xs) { ... } 

funzionare senza aver bisogno di un null-check. Ora, questo è quello che attualmente faccio, a seconda del contesto più ampio:

var xs = f() ?? new X[0];    // when xs is assigned, sometimes 
for (var x in xs ?? new X[0]) { ... } // inline, sometimes 

Ora, mentre il sopra è perfettamente bene per me - che è, se c'è qualche "testa extra" con la creazione della matrice oggetto che semplicemente non mi interessa - mi chiedevo:

c'è "immutabile vuoto IEnumerable/IList" Singleton in C#/NET.? (E, anche se non, c'è un modo "migliore" per gestire il caso descritto sopra?)

Java ha Collections.EMPTY_LIST immutabile Singleton - "ben tipato" tramite Collections.emptyList<T>() - che serve a questo scopo, anche se io Non sono sicuro se un concetto simile potrebbe funzionare anche in C# perché i farmaci generici sono gestiti in modo diverso.

Grazie.

+0

Beh, dannazione :) Questo è quello che ottengo per concentrarsi su List/IList e non Enumerable/IEnumerable, grazie a tutti - voti tutto intorno. –

+0

http: // stackoverflow.it/questions/3229698/how-can-i-return-an-empty-enumerable –

+1

'matrice statica pubblica Array {public statico readonly T [] Empty = new T [0]; } 'e può essere chiamato come:' Array .Empty'. Ho chiesto a questo proposito [qui in CodeReview] (http://codereview.stackexchange.com/q/20417/17039). –

risposta

68

Siete alla ricerca di Enumerable.Empty<int>();

In altre notizie Java lista vuota fa schifo, perché l'interfaccia List espone metodi per aggiungere elementi alla lista che gettare eccezioni.

+0

Questo è un punto molto valido! Forse garantisce una nuova domanda SO? –

+1

Sei stato qualche secondo lento e nessun link alla documentazione _ * finger shake * _ ;-) Ma l'accettazione per espandere il commento di svicks. –

+0

Anche gli altri ragazzi hanno ottenuto più upvotes quindi siamo pari :) Vorrei pubblicare una domanda ma ora vado a letto e non potrò seguire la domanda. Perché non pubblicarlo da solo? – Stilgar

17

Penso che stiate cercando Enumerable.Empty<T>().

L'elenco vuoto singleton non ha molto senso, perché le liste sono spesso modificabili.

10

Penso che l'aggiunta di un metodo di estensione è un ambiente pulito, grazie alternativi per la loro capacità di gestire i null - qualcosa come:

public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> list) 
    { 
    return list ?? Enumerable.Empty<T>(); 
    } 

    foreach(var x in xs.EmptyIfNull()) 
    { 
    ... 
    } 
1

Microsoft ha implementato `Qualsiasi()' come questo (source)

public static bool Any<TSource>(this IEnumerable<TSource> source) 
{ 
    if (source == null) throw new ArgumentNullException("source"); 
    using (IEnumerator<TSource> e = source.GetEnumerator()) 
    { 
     if (e.MoveNext()) return true; 
    } 
    return false; 
} 

Se si desidera salvare una chiamata sullo stack di chiamate, invece di scrivere un metodo di estensione che chiama !Any(), è sufficiente effettuare nuovamente le seguenti tre modifiche:

public static bool IsEmpty<TSource>(this IEnumerable<TSource> source) //first change (name) 
{ 
    if (source == null) throw new ArgumentNullException("source"); 
    using (IEnumerator<TSource> e = source.GetEnumerator()) 
    { 
     if (e.MoveNext()) return false; //second change 
    } 
    return true; //third change 
} 
1

L'utilizzo di Enumerable.Empty<T>() con gli elenchi ha uno svantaggio. Se si consegna Enumerable.Empty<T> nel costruttore lista, viene allocata una matrice di dimensione 4. Ma se si consegna uno Collection vuoto nella funzione di costruzione dell'elenco, non si verifica alcuna allocazione. Pertanto, se si utilizza questa soluzione per tutto il codice, molto probabilmente uno dei numeri IEnumerable verrà utilizzato per creare un elenco, con conseguenti allocazioni non necessarie.