Вільно конвертувати між Список <T> і IEnumerable <T>


103

Як я можу конвертувати a List<MyObject>в, IEnumerable<MyObject>а потім знову?

Я хочу це зробити для того, щоб запустити ряд висловлювань LINQ у списку, наприклад Sort()


Це висвітлюється в цьому питанні stackoverflow.com/questions/31708/…
Іван,

Відповіді:


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

30
Однак остерігайтеся, що myEnumarable - це той самий об’єкт об'єкта, що і myList, але listAgain - це не той самий об'єкт, що і myEnumerable. Залежно від того, що ви хочете зробити і що таке myEnumerable, "Список <string> listAgain = myEnumerable як список <string>;" може бути і краще.
ChrisW

1
Кріс: О так, ви, звичайно, маєте рацію, але інтерфейс IEnumerable <T> є незмінним, тому він не спричинятиме проблем у цьому напрямку, а відкидання назад просто відчуває себе брудним, коли у вас є функція, яка піклується про безпеку типу.
Тамас Цінеге

1
Ви також можете просто використовувати оригінальний об'єкт myList. (Напевно, у мене справді не виникає питання)
sth

6
Просто, якщо він редагує myList, він би редагував myEnumrable, але якщо він редагує listAgain, тоді він не редагує myEnumerable.
ChrisW

15
Не забувайте, using System.Linq;або ви не зможете ToList ()
Джейсон

21

A List<T>- це IEnumerable<T>, так що насправді немає необхідності "перетворювати" a List<T>в an IEnumerable<T>. Оскільки a List<T>- це IEnumerable<T>, ви можете просто призначити List<T>змінну типу IEnumerable<T>.

Навпаки , не кожен IEnumerable<T>є List<T>збитком, тож вам доведеться викликати ToList()метод-член IEnumerable<T>.


4
Технічно ToList є членом методу System.Linq.Numerable
Емі Б

2
Я думаю, що ти можеш просто поставити IEnumerable у Список, як Девід каже, що це.
абатищев

9

A List<T>вже є IEnumerable<T>, тому ви можете запускати оператори LINQ безпосередньо на своїй List<T>змінній.

Якщо ви не бачите методів розширення LINQ, як OrderBy()я думаю, це тому, що у вас немає using System.Linqдирективи у вихідному файлі.

Вам потрібно конвертувати результат виразу LINQ в List<T>явно, хоча:

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

"Якщо ви не бачите таких методів розширення LINQ, як OrderBy ()" Це була моя проблема, дякую.
RyPope

5

Убік: Зауважте, що стандартні оператори LINQ (згідно з попереднім прикладом) не змінюють існуючий список - list.OrderBy(...).ToList()створюватимуть новий список на основі переупорядкованої послідовності. Однак досить легко створити метод розширення, який дозволяє використовувати лямбда з 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)));
}

Тоді ви можете використовувати:

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

Це оновлює наявний список таким же чином, List<T>.Sortяк і зазвичай.


Невелике виправлення цього твердження: стандартні оператори LINQ не змінюють існуючий список; натомість вони створюють новий IEnumerable, який містить логіку, необхідну для виконання своєї роботи. Однак ця логіка насправді не виконується до запиту IEnumerator.
Воєслав Стойкович

@ Войслав - Я мав на увазі в контексті попереднього прикладу, який закінчувався ToList- я все ж уточню .
Марк Гравелл

1

Перетворення List<T>наIEnumerable<T>

List<T>реалізацій IEnumerable<T>(та багатьох інших, таких як IList<T>, ICollection<T>), тому немає необхідності перетворювати Список назад в IEnumerable, оскільки він вже є IEnumerable<T>.

Приклад:

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;

Ви також можете використовувати Enumerable.AsEnumerable()метод

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

Перетворення IEnumerable<T>наList<T>

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

Це корисно в Entity Framework .


0

Щоб запобігти дублюванню в пам’яті, resharper пропонує таке:

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

.ToList () повертає новий незмінний список. Отже зміни в listAgain не впливають на мій список у відповіді @Tamas Czinege. Це в більшості випадків вірно, щонайменше, з двох причин: Це допомагає запобігти змінам однієї області, що впливає на іншу область (нещільне з'єднання), і це дуже легко читається, оскільки нам не слід розробляти код з проблемами компілятора.

Але є певні випадки, наприклад, перебуваючи в тісному циклі або працюючи над вбудованою або низькою системою пам’яті, де слід враховувати питання компілятора.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.