LINQ ToList()使所有记录成为协程的最后一个记录

时间:2013-04-20 01:18:33

标签: linq coroutine

我似乎有一个误解,因为如果我不附加ToList()命令,以下代码可以正常工作:

IEnumerable<ProcessorInfo> query = (
        from n in InfoGet(EMachineInfoDepth.LogicalProcessor)
        select n
    )
    .ToList();

InfoGet看起来像这样:

internal static IEnumerable<ProcessorInfo> InfoGet(EMachineInfoDepth depth)
{
    ProcessorInfo result = new ProcessorInfo();

    // loop through all workgroups
    foreach (Workgroup wg in workgroups_S)
    {
        result.Workgroup = wg;

        if (depth >= EMachineInfoDepth.NUMANode)
        {
            // loop through all NUMANodes
            foreach (NUMANode node in wg.NUMANodes)
            {
                result.NUMANode = node;

                if (depth >= EMachineInfoDepth.CPU)
                {
                    // loop through all CPUs
                    foreach (CPU cpu in node.CPUs)
                    {
                        result.CPU = cpu;

                        if (depth >= EMachineInfoDepth.Core)
                        {
                            // loop through all Cores
                            foreach (Core core in cpu.Cores)
                            {
                                result.Core = core;

                                if (depth >= EMachineInfoDepth.LogicalProcessor)
                                {
                                    // loop through all LogicalProcessors
                                    foreach (LogicalProcessor lp in core.LogicalProcessors)
                                    {
                                        result.LogicalProc = lp;

                                        yield return result;
                                    }
                                }
                                else
                                {
                                    yield return result;
                                }
                            }
                        }
                        else
                        {
                            yield return result;
                        }
                    }
                }
                else
                {
                    yield return result;
                }
            }
        }
        else
        {
            yield return result;
        }
    }
}

使用ToList(),我得到正确的计数,但所有记录都等于序列中的最后一个元素。虽然我知道这可能是我的复杂协程中的变量范围错误,因为在所有迭代中都会看到最终值,为什么代码在没有ToList()的情况下工作?

我的问题是:我误解了什么?

1 个答案:

答案 0 :(得分:1)

问题是,你一直在返回对同一个变量的引用:

ProcessorInfo result = new ProcessorInfo();

这是您实际创建新ProcessorInfo对象的唯一地方。您稍后只更改它的属性值,但仍然返回相同的对象。

您应该考虑在ProcessorInfo()课程中添加copy constructor,并用yield return result;替换每个yield return new ProcessorInfo(result);来电。这将是使其发挥作用的最简单方法。

更新

它可以看起来就像它有效一样当你在循环期间在某处保存了一些变量状态时:

foreach(var item in query)
{
    itemsList.Add(item);
    propertyList.Add(item.IntProperty);
}

此致电话itemsList将包含不正确的数据,而propertyList就可以了。