Il codice di esempio di Resharper per spiegare “Possibile enumerazione multipla di IEnumerable”

A volte Resharper avvisa su:

Possibile enumerazione multipla di IEnumerable

C’è una domanda SO su come gestire questo problema , e il sito ReSharper spiega anche le cose qui . Ha un codice di esempio che ti dice di farlo invece:

IEnumerable names = GetNames().ToList(); 

La mia domanda riguarda questo specifico suggerimento: questo non porterà ancora a enumerare attraverso la raccolta due volte nei cicli 2 per-ciascuno?

    GetNames() restituisce un object IEnumerable . Quindi se memorizzi quel risultato:

     IEnumerable foo = GetNames(); 

    Quindi, ogni volta che si enumera foo , viene chiamato di nuovo il metodo GetNames() (non letteralmente, non riesco a trovare un collegamento che spieghi correttamente i dettagli, ma vedere IEnumerable.GetEnumerator() ).

    Resharper vede questo e suggerisce di memorizzare il risultato dell’enumerazione di GetNames() in una variabile locale, ad esempio materializzandolo in un elenco:

     IEnumerable fooEnumerated = GetNames().ToList(); 

    Ciò assicurerà che il risultato GetNames() venga enumerato una sola volta, purché si fooEnumerated riferimento a fooEnumerated .

    Ciò è importante perché di solito si desidera enumerare solo una volta, ad esempio quando GetNames() esegue una chiamata al database (lenta).

    Poiché hai materializzato i risultati in una lista, non importa più che enumeriamo fooEnumerated due volte; starai su un elenco in memoria due volte.

    Ho trovato questo per avere il modo migliore e più semplice per comprendere più enumerazioni.

    C # LINQ: ansible enumerazione multipla di IEnumerable

    https://helloacm.com/c-linq-possible-multiple-enumeration-of-ienumerable-resharper/

    GetNames() non viene chiamato due volte. L’implementazione di IEnumerable.GetEnumerator() viene chiamata ogni volta che si desidera enumerare la raccolta con foreach . Se all’interno IEnumerable.GetEnumerator() viene effettuato un calcolo costoso, ciò potrebbe essere un motivo da considerare.

    Sì, lo annoterai due volte senza dubbio. ma il punto è se GetNames() restituisce una query lazy linq che è molto costosa da calcolare, quindi calcolerà due volte senza una chiamata a ToList() o ToArray() .