如何创建字典的副本<;int,列表<;int>>;而不影响原件(C#)
本文关键字:int gt lt 影响 何创建 副本 创建 字典 列表 | 更新日期: 2023-09-27 18:20:13
我在C#中使用字典,我花了几个小时弄清楚为什么我的程序不工作,原因是当我操作我制作的字典的副本时,这些操作也会出于某种原因影响原始字典。
我把我的问题归结为以下例子:
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);
}
}
在这段代码中,当我将一个元素添加到副本中键1对应的列表中时,这个元素也会出现在原始字典中。
当我在网上搜索时,它似乎与"引用类型"有关,推荐的修复程序似乎总是涉及类似的代码
Dictionary<int, List<int>> Dcopy = new Dictionary<int, List<int>>(D);
我确实把它包括在我的程序中,但由于某种原因,这不起作用。
关于为什么它在我的情况下不起作用,有什么建议吗?
致以最良好的问候。
您正在进行浅层复制,而不是深度复制。你基本上需要遍历你的字典并创建新的列表
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
,这是一种值类型,因此您不需要比列表更深地"克隆"。如果列表中包含引用类型,那么您还必须另外克隆它们,并可能一直克隆任何引用属性。
dictionary copy构造函数生成字典的浅副本。由于值是列表(引用类型),因此不会克隆列表。如果你想制作深度副本,你还需要克隆值:
Dictionary<int, List<int>> Dcopy = D.ToDictionary(kvp => kpv.Key,
kvp => kvp.Value.ToList());
由于这些值是值类型的集合,因此不需要关闭列表的内容-克隆列表本身就足够了。键也是如此——它们是值类型,因此不需要克隆。
如果您不需要列表的深度副本,为什么不简单地使用.NET提供的构造函数,避免扩展调用呢?
Dictionary<int, List<int>> Dcopy = new Dictionary<int,List<int>>(D);