C#如何判断IEnumerable是否可变?

时间:2010-05-18 09:41:16

标签: c# ienumerable mutable

我想要一种方法来更新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; }
    }

2 个答案:

答案 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创建的所有新对象放入列表中,它们会保留在列表中,从而导致UpdateYesterdayforeach循环将引用相同的对象(您创建的列表中的对象)。

这有意义吗?我认为这很可能是您遇到的问题(在这种情况下,答案确实是在内存中构建一个集合,例如List<Job>,您可以从中访问要操作的成员。)

回答你关于能够判断IEnumerable是否可变的问题,但是......好吧,我真的不认为 是可能的。

我删除了旧答案,因为新答案似乎是OP需要的。