【问题标题】:C# How can I tell if an IEnumerable is Mutable?C# 如何判断 IEnumerable 是否可变?
【发布时间】:2010-05-18 09:41:16
【问题描述】:

我想要一种方法来更新 IEnumerable 的某些条目。我发现对条目进行 foreach 并更新值失败了,因为我在后台克隆了集合。这是因为我的 IEnumerable 由一些 LINQ->SQL 查询支持。

通过更改获取列表的方法,我改变了这种行为,列表始终是可变的,因此该方法会更改列表中的实际对象。而不是要求传递一个列表,有没有我可以使用的可变接口?

    // 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; }
    }

【问题讨论】:

    标签: c# ienumerable mutable


    【解决方案1】:

    您根本没有在此处更改 list - 集合本身可能是不可变的,并且此代码仍然可以“工作”。您正在更改集合中项目中的数据。

    想象一排房子 - 这是非常不可变的(创建或摧毁房子很棘手),但您仍然可以更改这些房子的内容。

    所以,你真正需要知道的是集合的 元素 是否会被克隆......每次你是否会得到一个“新”工作的集合执行查询,或者是否使用现有对象。

    【讨论】:

    • 我同意这个问题措辞不当,我的断言可能不正确。我的“作业”类有公共设置方法,但是如果我的原始代码与容器行为无关,我无法理解为什么我的原始代码不起作用。
    • @Logan:在检索项目时自动克隆项目将是一种非常奇怪的容器 - 但使用 LINQ to SQL 查询,您可能会看到 like 的行为.
    【解决方案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&lt;Job&gt;,您可以从中访问成员以进行操作)。

    在回答您关于能够判断 IEnumerable 是否可变的问题时,虽然...好吧,我真的不认为 是可能的。

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

    【讨论】:

    • 宾果游戏!这正是我正在做的事情,非常感谢您使用您卓越的心灵感应能力并花时间解释可能是什么原因以及 ToList 解决问题的原因。我将在几分钟后更新具体类型,并将其传递给 UpdateYesterday。
    • @Logan:哈,很好!很高兴帮助:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-17
    • 2013-06-04
    • 1970-01-01
    • 2018-11-10
    • 1970-01-01
    • 2018-06-30
    相关资源
    最近更新 更多