如何创建Dictionary <int,list <int>&gt;的副本?不影响原始(C#)?

时间:2015-11-02 21:44:39

标签: c# dictionary

我在C#中使用词典,我花了几个小时搞清楚为什么我的程序不起作用,原因是当我操作我制作的字典副本时,这些操作也是由于某种原因影响原始字典。

我已将问题归结为以下示例:

const React = require('react');
const ReactDOM = require('react-dom');

class Item extends React.Component {
  render(){
    let item = this.props.store.item;
    return (
      <div>
         <h1><a href={items.url}>{item.title}</a></h1>
         <h2>{item.score} - {item.by.id}</h2>
         <hr />
      </div>
    );
  }
};

// Create the mount point and attach it to the DOM
const mountNode = document.createElement('div');
document.body.appendChild(mountNode);

const item = {
  id: '1337',
  url: 'http://google.com',
  title: 'Google',
  score: 100,
  by: {id: 'clay'},
};
ReactDOM.render(
  <Item store={{item}} />, 
  mountNode
);

在此代码中,当我向副本中的键1对应的列表中添加元素时,此元素也会出现在原始字典中。

当我在线搜索时,它似乎与“引用类型”有关,推荐的修复似乎总是涉及类似于

的代码
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        Dictionary<int, List<int>> D = new Dictionary<int, List<int>>();
        List<int> L1 = new List<int>(){ 1, 2, 3 };
        List<int> L2 = new List<int>() { 4, 5, 6 };
        D.Add(1,L1);
        D.Add(2,L2);
        Dictionary<int, List<int>> Dcopy = new Dictionary<int, List<int>>(D);
        Dcopy[1].Add(4);
    }
}

我确实包含在我的程序中,但出于某种原因,这不起作用。

关于为什么它在我的情况下不起作用的任何建议,以及关于该做什么的任何建议?

最好的问候。

3 个答案:

答案 0 :(得分:6)

您正在进行浅层复制,而不是深层复制。您基本上需要遍历字典并创建新列表

var Dcopy = new Dictionary<int, List<int>>();
foreach (var entry in D)
{
    Dcopy.Add(entry.Key, new List<int>(entry.Value));
} 

或者您可以使用以下Linq而不是foreach

var DCopy = D.ToDictionary(entry => entry.Key, entry => new List<int>(entry.Value));

由于您的列表包含int,这是一种值类型,您不需要克隆&#34;比列表更深。相反,如果列表包含引用类型,那么您还必须另外克隆它们,并且可能还有任何引用属性。

答案 1 :(得分:4)

字典复制构造函数生成字典的副本。由于值是列表(引用类型),因此不会克隆列表。如果您想制作副本,您还需要克隆这些值:

    Dictionary<int, List<int>> Dcopy = D.ToDictionary(kvp => kpv.Key,
                                                      kvp => kvp.Value.ToList());

由于值是值类型的集合,因此无需关闭列表的内容 - 克隆列表本身就足够了。密钥相同 - 它们是值类型,因此不需要克隆。

答案 2 :(得分:-1)

如果您不需要列表的副本,为什么不简单地使用.NET提供的构造函数,避免扩展调用?

Dictionary<int, List<int>> Dcopy = new Dictionary<int,List<int>>(D);