如何创建字典的副本<;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);

我确实把它包括在我的程序中,但由于某种原因,这不起作用。

关于为什么它在我的情况下不起作用,有什么建议吗?

致以最良好的问候。

如何创建字典的副本<;int,列表<;int>>;而不影响原件(C#)

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

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);