在List <T>和IEnumerable <T>之间自由转换


Answers:


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

30
但是请注意,myEnumarable与myList是相同的对象实例,但listAgain与myEnumerable是不同的对象实例。根据您要执行的操作和myEnumerable是什么,“ List <string> listAgain = myEnumerable as List <string>;” 可能会更好。
ChrisW

1
Chrisw:哦,是的,您当然是对的,但是IEnumerable <T>接口是不可变的,因此它不会在该方向上引起问题,并且当您具有可以保护类型安全的函数时,回退只会让人感到肮脏
Tamas Czinege,09年

1
您也可以只使用原始的myList对象。(我想我真的没有得到这个问题)
某人

6
只是如果他编辑myList,那么他将在编辑myEnumrable,但是如果他编辑listAgain,那么他将不会在编辑myEnumerable。
ChrisW

15
别忘了,using System.Linq;否则您将无法ToList()
Jason

21

A List<T>是一个IEnumerable<T>,因此实际上不需要将a转换List<T>为一个IEnumerable<T>。由于a List<T>是an IEnumerable<T>,因此您可以简单地将a分配给List<T>type变量IEnumerable<T>

反之,并非每一个IEnumerable<T>都在List<T>讲习班,因此您必须调用的ToList()member方法IEnumerable<T>


4
从技术上讲,ToList是System.Linq.Enumerable的成员方法
Amy B

2
我认为您可以像David所说的那样将IEnumerable投射在List上。
abatishchev

9

A List<T>已经是IEnumerable<T>,因此您可以直接在List<T>变量上运行LINQ语句。

如果您没有看到像OrderBy()我猜的那样的LINQ扩展方法,那是因为您using System.Linq的源文件中没有指令。

但是,您确实需要将LINQ表达式结果转换回List<T>显式:

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

“如果看不到像OrderBy()这样的LINQ扩展方法,那就是我的问题,谢谢。
RyPope 2014年

5

另外:请注意,标准LINQ运算符(如前面的示例所示)不会更改现有列表- list.OrderBy(...).ToList()会基于重新排序的序列创建一个新列表。但是,创建扩展方法很容易,该方法允许您将lambda与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时才真正执行此逻辑。
Vojislav Stojkovic

@Vojislav-我的意思是在前面的示例中以ToList- 结尾,但是我会澄清。
马克·格雷韦尔

1

转换List<T>IEnumerable<T>

List<T>实现IEnumerable<T>(以及许多其他实现IList<T>, ICollection<T>),因此无需将List转换回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();

这在实体框架中很有用。


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答案中的myList。在大多数情况下,这是正确的,至少有两个原因:这有助于防止一个区域的更改影响另一区域(松耦合),并且它非常易读,因为我们不应该在设计时考虑编译器问题。

但是在某些情况下(例如处于紧密循环中或在嵌入式或低内存系统上工作),应考虑编译器注意事项。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.