Как я могу преобразовать a List<MyObject>
в a, IEnumerable<MyObject>
а затем обратно?
Я хочу сделать это, чтобы запустить серию операторов LINQ в списке, например Sort()
Ответы:
List<string> myList = new List<string>();
IEnumerable<string> myEnumerable = myList;
List<string> listAgain = myEnumerable.ToList();
using System.Linq;
иначе вы не сможете ToList ()
A List<T>
- это IEnumerable<T>
, поэтому на самом деле нет необходимости «конвертировать» a List<T>
в IEnumerable<T>
. Поскольку a List<T>
- это IEnumerable<T>
, вы можете просто присвоить List<T>
a переменной типа IEnumerable<T>
.
С другой стороны, не все IEnumerable<T>
- это List<T>
вне курса, поэтому вам придется вызвать ToList()
метод-член класса IEnumerable<T>
.
A List<T>
уже является IEnumerable<T>
, поэтому вы можете запускать операторы LINQ непосредственно для своей List<T>
переменной.
Если вы не видите методы расширения LINQ, как OrderBy()
я предполагаю, это потому, что у вас нет using System.Linq
директивы в исходном файле.
Однако вам нужно List<T>
явно преобразовать результат выражения LINQ обратно в :
List<Customer> list = ...
list = list.OrderBy(customer => customer.Name).ToList()
Кроме того: обратите внимание, что стандартные операторы 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
как и обычно.
ToList
- я все же поясню.
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 .
Чтобы предотвратить дублирование в памяти, resharper предлагает следующее:
List<string> myList = new List<string>();
IEnumerable<string> myEnumerable = myList;
List<string> listAgain = myList as List<string>() ?? myEnumerable.ToList();
.ToList () возвращает новый неизменяемый список. Таким образом, изменения в listAgain не влияют на myList в ответе @Tamas Czinege. Это верно в большинстве случаев по крайней мере по двум причинам: это помогает предотвратить изменения в одной области, влияющие на другую область (слабая связь), и она очень удобочитаема, поскольку мы не должны проектировать код с учетом проблем компилятора.
Но есть определенные случаи, например, нахождение в замкнутом цикле или работа со встроенной системой или системой с низким объемом памяти, где следует учитывать соображения компилятора.