Converti liberamente tra List <T> e IEnumerable <T>


Risposte:


148
List<string> myList = new List<string>();
IEnumerable<string> myEnumerable = myList;
List<string> listAgain = myEnumerable.ToList();

30
Attenzione, tuttavia, che myEnumarable è la stessa istanza di oggetto di myList, ma listAgain non è la stessa istanza di oggetto di myEnumerable. A seconda di cosa si desidera fare e di cosa sia myEnumerable, "List <string> listAgain = myEnumerable as List <string>;" potrebbe essere migliore.
ChrisW

1
Chrisw: Oh sì, hai ragione, naturalmente, ma l'interfaccia IEnumerable <T> è immutabile, quindi non causerà problemi in quella direzione e il casting risulta sporco quando hai una funzione che si prenderà cura della sicurezza dei tipi.
Tamas Czinege,

1
Puoi anche usare semplicemente l'oggetto originale myList. (Immagino di non aver capito davvero la domanda)
sth

6
È solo che se modifica myList, modificherà myEnumrable, ma se modifica listA di nuovo non modificherà myEnumerable.
ChrisW

15
Non dimenticare using System.Linq;o non sarai in grado di ToList ()
Jason

21

A List<T>è an IEnumerable<T>, quindi in realtà non è necessario "convertire" a List<T>in an IEnumerable<T>. Poiché a List<T>è an IEnumerable<T>, puoi semplicemente assegnare a List<T>a una variabile di tipo IEnumerable<T>.

Al contrario, non tutti IEnumerable<T>sono fuori corso List<T>, quindi dovrai chiamare il ToList()metodo membro di IEnumerable<T>.


4
Tecnicamente, ToList è un metodo membro di System.Linq.Enumerable
Amy B

2
Penso che tu possa semplicemente lanciare IEnumerable su List come David dice che è così.
abatishchev

9

A List<T>è già un IEnumerable<T>, quindi puoi eseguire istruzioni LINQ direttamente sulla tua List<T>variabile.

Se non vedi i metodi di estensione LINQ come OrderBy()immagino sia perché non hai una using System.Linqdirettiva nel tuo file sorgente.

List<T>Tuttavia, è necessario riconvertire il risultato dell'espressione LINQ in un esplicito:

List<Customer> list = ...
list = list.OrderBy(customer => customer.Name).ToList()

"Se non vedi i metodi di estensione LINQ come OrderBy ()" Questo era il mio problema, grazie.
RyPope

5

A parte: si noti che gli operatori LINQ standard (come nell'esempio precedente) non modificano l' elenco esistente : list.OrderBy(...).ToList()creeranno un nuovo elenco in base alla sequenza riordinata. È abbastanza facile, tuttavia, creare un metodo di estensione che ti consenta di utilizzare lambda con List<T>.Sort:

static void Sort<TSource, TValue>(this List<TSource> list,
    Func<TSource, TValue> selector)
{
    var comparer = Comparer<TValue>.Default;
    list.Sort((x,y) => comparer.Compare(selector(x), selector(y)));
}

static void SortDescending<TSource, TValue>(this List<TSource> list,
    Func<TSource, TValue> selector)
{
    var comparer = Comparer<TValue>.Default;
    list.Sort((x,y) => comparer.Compare(selector(y), selector(x)));
}

Quindi puoi usare:

list.Sort(x=>x.SomeProp); // etc

Questo aggiorna l' elenco esistente nello stesso modo in cui List<T>.Sortfa di solito.


Una leggera correzione a questa affermazione: gli operatori LINQ standard non cambiano l'elenco esistente; invece, creano un nuovo IEnumerable che contiene la logica necessaria per svolgere il loro lavoro. Tuttavia, questa logica non viene effettivamente eseguita finché non viene richiesto IEnumerator.
Vojislav Stojkovic

@Vojislav - intendevo nel contesto dell'esempio precedente che termina con ToList- chiarirò , però.
Marc Gravell

1

Conversione List<T>inIEnumerable<T>

List<T>implementa IEnumerable<T>(e molti altri come IList<T>, ICollection<T>) quindi non è necessario riconvertire un List in IEnumerable poiché è già unIEnumerable<T> .

Esempio:

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Person person1 = new Person() { Id = 1, Name = "Person 1" };
Person person2 = new Person() { Id = 2, Name = "Person 2" };
Person person3 = new Person() { Id = 3, Name = "Person 3" };

List<Person> people = new List<Person>() { person1, person2, person3 };

//Converting to an IEnumerable
IEnumerable<Person> IEnumerableList = people;

Puoi anche usare il Enumerable.AsEnumerable()metodo

IEnumerable<Person> iPersonList = people.AsEnumerable();

Conversione IEnumerable<T>inList<T>

IEnumerable<Person> OriginallyIEnumerable = new List<Person>() { person1, person2 };
List<Person> convertToList = OriginallyIEnumerable.ToList();

Ciò è utile in Entity Framework .


0

Per evitare la duplicazione in memoria, resharper suggerisce questo:

List<string> myList = new List<string>();
IEnumerable<string> myEnumerable = myList;
List<string> listAgain = myList as List<string>() ?? myEnumerable.ToList();

.ToList () restituisce un nuovo elenco non modificabile. Quindi le modifiche a listAgain non hanno effetto su myList nella risposta @Tamas Czinege. Questo è corretto nella maggior parte dei casi per almeno due ragioni: questo aiuta a prevenire i cambiamenti in un'area che influiscono sull'altra area (accoppiamento libero), ed è molto leggibile, poiché non dovremmo progettare codice con problemi di compilazione.

Ma ci sono alcuni casi, come trovarsi in un ciclo stretto o lavorare su un sistema incorporato o con poca memoria, in cui è necessario prendere in considerazione le considerazioni del compilatore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.