【发布时间】:2015-12-14 13:39:06
【问题描述】:
我有一个非常简单的程序,它创建一堆对象并遍历它们以设置每个对象的 Priority 属性。
static void Main(string[] args)
{
foreach (var obj in ObjectCreator.CreateObjectsWithPriorities())
Console.WriteLine(String.Format("Object #{0} has priority {1}",
obj.Id, obj.Priority));
}
class ObjectCreator
{
public static IEnumerable<ObjectWithPriority> CreateObjectsWithPriorities()
{
var objs = new[] { 1, 2, 3 }.Select(i => new ObjectWithPriority() { Id = i });
ApplyPriorities(objs);
return objs;
}
static void ApplyPriorities(IEnumerable<ObjectWithPriority> objs)
{
foreach (var obj in objs)
{
obj.Priority = obj.Id * 10;
Console.WriteLine(String.Format("Set priority of object #{0} to {1}", obj.Id, obj.Priority));
}
}
}
class ObjectWithPriority
{
public int Id { get; set; }
public int Priority { get; set; }
}
我希望 Main 方法中的 IEnumerable 包含具有修改优先级的对象。但是,它们都具有默认值 0。
这是日志:
Set priority of object #1 to 10
Set priority of object #2 to 20
Set priority of object #3 to 30
Object #1 has priority 0
Object #2 has priority 0
Object #3 has priority 0
这种行为的原因是什么?为了让我的优先事项发挥作用,我应该在这里改变什么?
【问题讨论】:
-
关于 LINQ 必须内化的两个重要事实:(1) 查询表达式的值是 查询,以及 (2) 查询是在 查询被执行。这些陈述似乎是重言式,但您的代码表明您不相信它们;你认为查询的价值就是查询的执行,执行两次只会执行一次。
-
@EricLippert,你说得对,我一直认为 IEnumerable 是我可以枚举的元素序列(顾名思义),而不是作为查询表示。如果我只需要循环遍历序列(并且从不添加/删除元素),我可以在整个程序中安全地使用 IEnumerable 而无需调用 ToList,这似乎也是有道理的。正如许多书籍/文章所建议的那样,“您应该使用最通用的类型”在方法/类/程序之间传递对象,这就是我在这里尝试做的。现在我发现它比这更复杂。
标签: c# foreach ienumerable