Convierta libremente entre List <T> e IEnumerable <T>

Respuestas:

148
List<string> myList = new List<string>();
IEnumerable<string> myEnumerable = myList;
List<string> listAgain = myEnumerable.ToList();
Tamas Czinege
fuente
30
Sin embargo, tenga en cuenta que myEnumarable es la misma instancia de objeto que myList, pero listAgain no es la misma instancia de objeto que myEnumerable. Dependiendo de lo que quiera hacer y de lo que sea myEnumerable, "List <string> listAgain = myEnumerable as List <string>;" podría ser mejor.
ChrisW
1
Chrisw: Oh, sí, tiene razón, por supuesto, pero la interfaz IEnumerable <T> es inmutable, por lo que no causará problemas en esa dirección y la conversión se siente sucia cuando tiene una función que se encarga de la seguridad de los tipos.
Tamas Czinege
1
También puede usar el objeto myList original. (Supongo que realmente no entiendo la pregunta)
algo
6
Es solo que si edita myList, estaría editando myEnumrable, pero si edita listAgain, no estaría editando myEnumerable.
ChrisW
15
No lo olvide using System.Linq;o no podrá ToList ()
Jason
21

A List<T>es un IEnumerable<T>, por lo que en realidad no es necesario 'convertir' List<T>a en un IEnumerable<T>. Como a List<T>es an IEnumerable<T>, simplemente puede asignar List<T>a una variable de tipo IEnumerable<T>.

Al revés, no todos IEnumerable<T>son fuera de List<T>curso, por lo que tendrás que llamar al ToList()método de miembro de IEnumerable<T>.

Frederik Gheysels
fuente
4
Técnicamente, ToList es un método miembro de System.Linq.Enumerable
Amy B
2
Creo que puedes lanzar IEnumerable en List como David dice que es.
abatishchev
9

A List<T>ya es an IEnumerable<T>, por lo que puede ejecutar declaraciones LINQ directamente en su List<T>variable.

Si no ve los métodos de extensión LINQ como OrderBy()supongo, es porque no tiene una using System.Linqdirectiva en su archivo fuente.

Sin List<T>embargo, debe convertir el resultado de la expresión LINQ a explícitamente:

List<Customer> list = ...
list = list.OrderBy(customer => customer.Name).ToList()
Dan Berindei
fuente
"Si no ve los métodos de extensión LINQ como OrderBy ()" Ese era mi problema, gracias.
RyPope
5

Aparte: tenga en cuenta que los operadores LINQ estándar (como en el ejemplo anterior) no cambian la lista existente ; list.OrderBy(...).ToList()crearán una nueva lista basada en la secuencia reordenada. Sin embargo, es bastante fácil crear un método de extensión que le permita usar lambdas 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)));
}

Entonces puedes usar:

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

Esto actualiza la lista existente de la misma forma que List<T>.Sortnormalmente lo hace.

Marc Gravell
fuente
Una pequeña corrección a esta afirmación: los operadores LINQ estándar no cambian la lista existente; en su lugar, crean un nuevo IEnumerable que contiene la lógica necesaria para hacer su trabajo. Sin embargo, esta lógica no se ejecuta realmente hasta que se solicita IEnumerator.
Vojislav Stojkovic
@Vojislav - Quería decir en el contexto del ejemplo anterior que termina con ToList- Sin embargo, lo aclararé.
Marc Gravell
1

Convirtiendo List<T>aIEnumerable<T>

List<T>implementa IEnumerable<T>(y muchos otros como IList<T>, ICollection<T>), por lo tanto, no es necesario convertir una Lista de nuevo a IEnumerable ya que ya es un IEnumerable<T>.

Ejemplo:

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;

También puedes usar el Enumerable.AsEnumerable()método

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

Convirtiendo IEnumerable<T>aList<T>

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

Esto es útil en Entity Framework .

Nipuna
fuente
0

Para evitar la duplicación en la memoria, resharper sugiere esto:

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

.ToList () devuelve una nueva lista inmutable. Por lo tanto, los cambios en listAgain no afectan a myList en la respuesta de @Tamas Czinege. Esto es correcto en la mayoría de los casos por al menos dos razones: Esto ayuda a prevenir cambios en un área que afectan a la otra área (acoplamiento flojo), y es muy legible, ya que no deberíamos diseñar código con preocupaciones del compilador.

Pero hay ciertos casos, como estar en un bucle cerrado o trabajar en un sistema integrado o con poca memoria, donde se deben tener en cuenta las consideraciones del compilador.

TamusJRoyce
fuente