[英]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.