代码之家  ›  专栏  ›  技术社区  ›  IamIC

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

  •  0
  • IamIC  · 技术社区  · 12 年前

    我似乎有一个误解,因为如果我不附加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 回复  |  直到 12 年前
        1
  •  1
  •   MarcinJuraszek    12 年前

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

    ProcessorInfo result = new ProcessorInfo();
    

    那是你唯一真正创造新事物的地方 ProcessorInfo 对象以后只更改它的属性值,但返回的对象仍然相同。

    您应该考虑添加 copy constructor 进入您的 ProcessorInfo() 类,并替换每个 yield return result; 与通话 yield return new ProcessorInfo(result); 。那将是最简单的方法。

    使现代化

    它可以 就像它的工作原理一样,例如,当你在循环中的某个地方保存了一些变量状态时:

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

    在那通电话之后 itemsList 将包含 不准确的 数据,而 propertyList 会很好的。