C#IEnumerable在子方法中被重置

时间:2017-09-21 10:36:47

标签: c# linq ienumerable

我有以下方法:

private static List<List<job>> SplitJobsByMonth(IEnumerable<job> inactiveJobs)
{
    List<List<job>> jobsByMonth = new List<List<job>>();

    DateTime cutOff = DateTime.Now.Date.AddMonths(-1).Date;
    cutOff = cutOff.AddDays(-cutOff.Day + 1);

    List<job> temp;
    while (inactiveJobs.Count() > 0)
    {
        temp = inactiveJobs.Where(j => j.completeddt >= cutOff).ToList();
        jobsByMonth.Add(temp);
        inactiveJobs = inactiveJobs.Where(a => !temp.Contains(a));
        cutOff = cutOff.AddMonths(-1);
    }

    return jobsByMonth;
}

它旨在按月拆分工作。 'job'是一个类,而不是一个结构。在while循环中,每次迭代都会重置传入的IEnumerable以删除已处理的作业:

inactiveJobs = inactiveJobs.Where(a => !temp.Contains(a));

通常,这会大大减少此集合的内容。但是,在下一次迭代中,行:

temp = inactiveJobs.Where(j => j.completeddt >= cutOff).ToList();

将inactiveJobs对象恢复到传递给方法时的状态 - 因此集合再次满了。 我通过稍微重构这个方法解决了这个问题,但我很好奇为什么会出现这个问题,因为我无法解释它。任何人都可以解释为什么会这样吗?

3 个答案:

答案 0 :(得分:1)

为什么不直接使用小组?

    private static List<List<job>> SplitJobsByMonth(IEnumerable<job> inactiveJobs)
    {
        var jobsByMonth = (from job in inactiveJobs
                            group job by new DateTime(job.completeddt.Year, job.completeddt.Month, 1)
                            into g
                            select g.ToList()).ToList();
        return jobsByMonth;
    }

答案 1 :(得分:0)

这是因为延迟执行LINQ的Where

当你这样做时

inactiveJobs = inactiveJobs.Where(a => !temp.Contains(a));

在您开始迭代IEnumerable之前,实际上并未进行任何评估。如果您在ToList之后添加Where,则会立即进行迭代,因此interactiveJobs的内容会减少:

inactiveJobs = inactiveJobs.Where(a => !temp.Contains(a)).ToList();

答案 2 :(得分:0)

LINQ 中,查询有两种不同的执行行为:立即延迟

查询实际上是在迭代查询变量时执行的,而不是在创建查询变量时执行的。这称为延迟执行。

您还可以强制查询立即执行,这对缓存查询结果非常有用。

为了在你的行末添加.ToList()

inactiveJobs = inactiveJobs.Where(a => !temp.Contains(a)).ToList();

这会立即执行创建的查询并将结果写入您的变量。

您可以详细了解this example Here