在 .net-core 中使用 linq 语句时,IEnumerable 和 List 之间出现意外差异?
在 .net-core 中使用 linq 语句时,IEnumerable 和 List 之间出现意外差异?
这个问题已经有答案了:
IEnumerable和List - 该使用哪个?它们怎么工作?
当我在Select()语句的末尾添加.ToList()时,它的效果与预期相符。
在这种情况下,IEnumerable和List有什么区别?
class Foo{ public string Name { get; set; } public Guid Id { get; set; } } class Program { static void Main(string[] args) { var list = new List(){ "first", "last" }; var bar = list.Select(x => new Foo { Name = x, Id = Guid.NewGuid() }); //.ToList(); Console.WriteLine("bar Count = " + bar.Count()); Console.WriteLine(); for (int i = 0; i < 3; i++) { Console.WriteLine(bar.First().Name + " " + bar.First().Id); Console.WriteLine(bar.Last().Name + " " + bar.Last().Id); Console.WriteLine(); } } }
结果:
examples Count = 2
first 1fabd003-340c-44a4-81ca-1908f206ccdb
last 213f40c9-0705-4676-ad1f-73de21c5bc62
first 9bc117e5-1f10-4855-af95-46258b39955c
last cd787227-12d9-4e25-88bc-634369d85671
first c787e081-8dd3-475c-bf24-44e5f103ed3a
last 7a72080d-2dee-47b1-a55d-af0a7665d0ea
带有.ToList()的结果
bar Count = 2
first 3c1d4f1d-eecd-438a-86a4-e7db0680cad3
last cba1867d-d246-477e-b938-0f9cce457a5c
first 3c1d4f1d-eecd-438a-86a4-e7db0680cad3
last cba1867d-d246-477e-b938-0f9cce457a5c
first 3c1d4f1d-eecd-438a-86a4-e7db0680cad3
last cba1867d-d246-477e-b938-0f9cce457a5c
使用Select
时,您正在定义惰性枚举,这意味着您正在定义如何生成可枚举值的规则,但实际上还没有生成值本身。惰性枚举 (又名“延迟加载”) 只是蓝图,没有数据并且不执行任何代码。
因此,当您调用bar.First()
和bar.Last()
时,您正在触发枚举开始生成一些值。每次这样做,它将生成全新的值。这意味着每次您在bar
上调用某些操作时,它都将通过新的Guid.NewGuid()
调用生成新的值,自然会导致每次生成新的GUID。
然而,如果您在可枚举对象上调用ToList()
,则会生成可枚举对象中的值,然后将它们缓存到List
中。现在,当您调用bar.First()
和bar.Last()
时,您正在引用List
中第一个和最后一个元素的静态值,这些值不会改变。