2011-10-20 16 views
6

So che IEnumerable è stato discusso più volte qui, ma non sono riuscito a trovare la risposta alla mia domanda specifica, quindi lo presenterò come una nuova domanda.Enumerazione multipla di IEnumerable

Si consideri il seguente frammento di codice:

static void Main(string[] args) 
    { 

     List<string> testList = new List<string> {"Test", "Test1", "Test1"}; 
     IEnumerable<string> filtered = testList.Where(x => x == "Test1"); 

     DoSomeWork(filtered); 
     DoSomeMoreWork(filtered); 
    } 

    public static void DoSomeWork(IEnumerable<string> items) 
    { 
     foreach (var item in items) 
     { 
      Console.WriteLine("do some work"); 
     } 
    } 

    public static void DoSomeMoreWork(IEnumerable<string> items) 
    { 
     foreach (var item in items) 
     { 
      Console.WriteLine("do some more work"); 
     } 
    } 

ho ragione, che questo provoca non solo i due elementi in "filtrati" per iterare due volte, ma in realtà le voci in "LISTA-TEST"? Quindi, considerando che "testList" era una grande lista con 10000 elementi e "filtrato" lo riduce a 10 elementi, sarebbe più intelligente fare "filtrare" un elenco (alias use var e aggiungere append ToList() alla fine)

MODIFICA: Questa è la domanda più imbarazzante che abbia mai posto qui. Sapevo che sarebbe stato male iterare un IQueryable, ad esempio perché ciò avrebbe comportato il recupero dei dati due volte dal DB. Tuttavia non ero esattamente sicuro sulle liste di memoria. Vorrei cancellare la domanda se potessi ;-)

risposta

0

List è ultimatly ereditare da IEnumrable controllare questo

public class List<T> : IList<T>, ICollection<T>, 
    IEnumerable<T>, IList, ICollection, IEnumerable 

Una cosa di più è possibile creare elenco di IEnurable utilizzando il seguente costruttore avaialble

public List(
    IEnumerable<T> collection 
) 

EDIT

L'elenco filtrato derivedi.e viene ripetuto due volte con entrambi i metodi ma con nd .ToList() metodo alla fine.

IEnumerable<string> filtered = testList.Where(x => x == "Test1").ToList(); 

http://msdn.microsoft.com/en-us/library/fkbw11z0.aspx

+0

Sì, lo so. Ma la domanda è.DoSomeWork() e DoSomeMoreWork() causeranno entrambi iterando la lista grande o faranno solo un'iterazione del sottoinsieme. – Christoph

+0

@Christoph - la risposta è ora modificata ..... –

+0

Meglio usare. ToArray che ToList per questo uso: gli array sono un po 'più efficienti, ma soprattutto non consentono l'aggiunta/rimozione, evitando una flessibilità non necessaria (evitando così confusione e bug). –

1

La grande lista sarà ribadito due volte. se non lo vuoi, puoi "materializzare" la restrizione.

var filtered = testList.Where(x => x == "Test1").ToList(); 

E ci sono molte risposte che ti dicono questo. Si dovrebbe avere cercato meglio :-)

0

sarebbe più intelligente per fare "filtrata" una lista (aka utilizzare var e sufficiente aggiungere ToList() alla fine)

Sì, soprattutto in termini di Linq-To-Entities ecc.

La restituzione di un IEnumerable con linq consente un'esecuzione diversa. Quando si aggiunge ToList() alla fine, l'elenco viene restituito proprio lì.

Vedi http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-execution.aspx

7

La grande lista verrà ripetuto due volte. Per controllare che ciò avvenga realmente modificare la tua ricerca per:

List<string> testList = new List<string> { "Test", "Test1", "Test1" }; 
IEnumerable<string> filtered = from t in testList 
           where t == "Test1" 
           select t; 

Se quindi impostare un punto di interruzione da parte 'dove t == 'Test1', si vedrà che il debugger colpisce questa linea per entrambe le iterazioni.

+0

Ah, si. Giusto. Grazie per il suggerimento! – Christoph