【问题标题】:How do you return a copy of original List<T> from Func<T, TResult>?如何从 Func<T, TResult> 返回原始 List<T> 的副本?
【发布时间】:2010-10-11 13:08:09
【问题描述】:

我发现(以一种艰难的方式)正在枚举的集合不能在“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 不会返回副本。 有没有办法退回副本?

*EDITJaredPar'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();
    }

*EDIT:最终结果(优化)

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

【问题讨论】:

  • 由于您并没有真正使用列表(例如,不添加或删除条目),请使用 ToArray() 代替。无论如何,ToList() 大致转换为 ToArray(),但要贵得多。
  • 感谢您的意见,chuckj。我认为在重构时我需要在某个地方停下来。但是当我遇到类似情况时,我会听取您的建议。

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


【解决方案1】:

一旦你更改了一个 Enumerable 类,你原来的枚举数可能会失效,因此需要创建一个副本并在那里进行修改。

【讨论】:

    【解决方案2】:

    您可以使用普通的 for,而不是使用 foreach。但是,添加/删除项目时要小心,它会更改集合内元素的索引。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 谢谢;这就是我选择的路径。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-18
      • 2013-11-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多