【发布时间】:2020-11-25 14:23:41
【问题描述】:
假设我有一个非常简单的引用类型,称为Person。
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
我使用 LINQ 创建一个 IEnumerable 调用 peopleEnum,代码如下。
var ages = new int[] { 1, 2, 3, 4, 5 };
var peopleEnum = ages.Where(a => a > 1)
.Select(a => new Person
{
Name = a.ToString(),
Age = a
});
我的理解是因为Person是引用类型,所以peopleEnum里面的元素应该是可变的。但我发现他们不是。
var person = peopleEnum.Single(p => p.Age == 4);
person.Name = "Four";
foreach (var p in peopleEnum)
{
Console.WriteLine($"{p.Name}, {p.Age}");
}
预期输出。
2, 2
3, 3
Four, 4
5, 5
实际输出。
2, 2
3, 3
4, 4
5, 5
但是,如果我以不同的方式创建 IEnumerable<Person>。
var people = new Person[]
{
new Person{ Name = "1", Age = 1 },
new Person{ Name = "2", Age = 2 },
new Person{ Name = "3", Age = 3 },
new Person{ Name = "4", Age = 4 },
new Person{ Name = "5", Age = 5 },
};
var peopleEnum2 = people.Where(p => p.Age > 1);
那么peopleEnum2 中的元素将是可变的。
var person = peopleEnum2.Single(p => p.Age == 4);
person.Name = "Four";
foreach (var p in peopleEnum2)
{
Console.WriteLine($"{p.Name}, {p.Age}");
}
输出
2, 2
3, 3
Four, 4
5, 5
哪些规则确定IEnumerable<T> 中的元素是否可变?
【问题讨论】:
-
在您的示例中,您枚举了
IEnumerable<T>两次。当IEnumerable<T>是一个具体的列表或数组时,多次枚举每次都会产生相同的元素。在您的第一个示例中,每次枚举时都会“动态”和“按需”创建元素,这就是为什么每次都会获得不同的元素。 -
当您执行
Single时,它会运行创建人员对象的代码。然后,当您运行foreach时,它会再次运行该代码,创建 4 个新对象。这称为延迟执行。
标签: c# linq immutability ienumerable