如何从Func <t,tresult =“”>返回原始List <t>的副本?</t,> </t>

时间:2009-03-05 15:37:51

标签: c# linq delegates .net-3.5 c#-3.0

我发现(以一种困难的方式)在“Foreach”语句中无法修改被枚举的集合

  

“集合已被修改;枚举操作可能无法执行。”

现在,我提出的解决方案是创建一个包含字典键的相同大小的虚拟集合,并枚举它以修改相关集合。

    private void InvalidateAuthenticatedNodes()
    {
        var dummy = new Dictionary<int, bool>(_AuthenticatedNodes.Count);
        foreach (var nodeId in _AuthenticatedNodes.Keys)
            dummy[nodeId] = false;

        foreach (var nodeId in dummy.Keys)
            _AuthenticatedNodes[nodeId] = false;

        ClearAuthenticatedDateTime();
    }

以上代码工作正常;我正在重构上面的代码以使用Func委托返回密钥的副本,如下所示

    private void InvalidateAuthenticatedNodes()
    {
        var getNodeIds = 
            new Func<Dictionary<int, bool>, IEnumerable<int>>(
                nodes => nodes.Select(node => node.Key));
        foreach (var nodeId in getNodeIds(_AuthenticatedNodes))
        {
            _AuthenticatedNodes[nodeId] = false;
        }

        ClearAuthenticatedDateTime();
    }

与我的预期不同, getNodeIds 不会返回副本。 有没有办法返回副本?

*编辑JaredPar's answer之前的临时结果

与JaredPar的回答相似,但他更简洁,我回答了他的回答。 但这是我想出来的类似结果。

    private void InvalidateAuthenticatedNodes()
    {
        var getNodeIds = 
            new Func<Dictionary<int, bool>, IEnumerable<int>>(nodes => 
                nodes.Select(node => node.Key));
        foreach (var nodeId in getNodeIds(_AuthenticatedNodes).ToList())
        {
            _AuthenticatedNodes[nodeId] = false;
        }

        ClearAuthenticatedDateTime();
    }

*编辑:最终结果(精炼)

_AuthenticatedNodes.Keys.ToList().ForEach(
    nodeId => _AuthenticatedNodes[nodeId] = false);

3 个答案:

答案 0 :(得分:4)

只需将.ToList()添加到集合的末尾,它就会自动返回列表的完整副本。

foreach (var nodeId in _AuthenticatedNodes.Keys.ToList())
    ...

答案 1 :(得分:1)

您可以使用法线来代替使用foreach。但是,添加/删除项目时要小心,它会更改集合中元素的索引。

答案 2 :(得分:1)

更改Enumerable类后,原始枚举器可能无效,因此需要创建副本并在那里进行修改。