繁体   English   中英

为什么IEnumerable.ToList会生成新对象

[英]Why does IEnumerable.ToList produce new objects

public class TestClass
{
   public int Num { get; set; }
   public string Name { get; set; }
}

IEnumerable<TestClass> originalEnumerable
   = Enumerable.Range(1, 1).
                Select(x => new TestClass() { Num = x, Name = x.ToString() });

List<TestClass> listFromEnumerable = originalEnumerable.ToList();

// false
bool test = ReferenceEquals(listFromEnumerable[0], originalEnumerable.ElementAt(0)); 

如果我修改复制的对象,原始文件不会更改。

我从中理解, System.Linq.IEnumerable<T>集合总是会生成新对象,即使它们在调用ToList() / ToArray()时是引用类型? 我错过了一些东西,因为其他SO问题坚持只有复制参考。

实际上,这是错误的原因是因为你的枚举实际上被枚举了两次 ,一次是在调用originalEnumerable.ToList() ,第二次是在调用originalEnumerable.ElementAt(0)

由于它枚举了两次,因此每次枚举时都会创建新对象。

你错过了Enumerable.Range是懒惰的事实,所以这行实际上只产生内存中的查询定义:

IEnumerable<TestClass> originalEnumerable
   = Enumerable.Range(1, 1).
                Select(x => new TestClass() { Num = x, Name = x.ToString() });

调用ToList()会触发查询并使用新项创建列表:

List<TestClass> listFromEnumerable = originalEnumerable.ToList();

在这里调用originalEnumerable.ElementAt(0)

bool test = ReferenceEquals(listFromEnumerable[0], originalEnumerable.ElementAt(0)); 

再次触发查询,并生成另一个新项目。

更新

所以你应该说, Enumerable.Range生成新项目,而不是ToList()

如果您的源集合已经被评估(例如TestClass[]数组) ToList()将不会创建新项目:

IEnumerable<TestClass> originalEnumerable
   = Enumerable.Range(1, 1).
                Select(x => new TestClass() { Num = x, Name = x.ToString() })
                .ToArray();

List<TestClass> listFromEnumerable = originalEnumerable.ToList();

// true
bool test = ReferenceEquals(listFromEnumerable[0], originalEnumerable[0]); 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM