我想要一种方法来更新IEnumerable的某些条目。我发现在条目中做一个foreach并更新值失败,因为我在克隆集合的后台。这是因为我的IEnumerable得到了一些LINQ-> SQL查询的支持。
通过更改方法来获取List我已经改变了这种行为,Lists总是可变的,因此该方法改变了列表中的实际对象。而不是要求传递List是否有可以使用的Mutable接口?
// Will not behave as consistently for all IEnumerables
public void UpdateYesterday (IEnumerable<Job> jobs) {
foreach (var job in jobs.Where(x => x.date == Yesterday)) {
job.done = true;
}
}
...
public class Job {
...
public DateTime Date { get; set; }
}
答案 0 :(得分:15)
你根本没有更改列表 - 集合本身可能是不可变的,而且这段代码仍然可以“正常工作”。您正在更改集合中项目的数据。
想象一排房子 - 这是不可改变的(创建或摧毁房子很棘手)但你仍然可以改变这些房屋的内容。
所以,你真正需要知道的是,该集合的元素是否将被克隆......每次你是否会获得一系列“新”工作执行查询,或者是否使用现有对象。
答案 1 :(得分:2)
这是可能发生的一种假设方式。假设您有一个方法可以获取现有数据源,并且从该来源创建 Job
个对象。
这样的事情:
public IEnumerable<Job> GetJobs() {
var rows = GetRowsFromDatabaseTable();
foreach (var row in rows)
yield return new Job(row.Name, row.Date, row.Etc);
}
然后,如果您有代码执行此操作:
var jobs = GetJobs();
UpdateYesterday(jobs);
foreach (var job in jobs)
Console.WriteLine(job);
您会发现使用Console.WriteLine
打印的作业未反映您在UpdateYesterday
中执行的更新。这是因为UpdateYesterday
将枚举GetJobs
创建的新对象,然后您的foreach
循环将枚举创建的一组新对象(再次)GetJobs
。
另一方面,如果您只是将第一行改为:
var jobs = GetJobs().ToList();
然后您可以将GetJobs
创建的所有新对象放入列表中,它们会保留在列表中,从而导致UpdateYesterday
和foreach
循环将引用相同的对象(您创建的列表中的对象)。
这有意义吗?我认为这很可能是您遇到的问题(在这种情况下,答案确实是在内存中构建一个集合,例如List<Job>
,您可以从中访问要操作的成员。)
回答你关于能够判断IEnumerable
是否可变的问题,但是......好吧,我真的不认为 是可能的。
我删除了旧答案,因为新答案似乎是OP需要的。