【问题标题】:How to make deep copy of a dictionary within Dictionary in c#? [duplicate]如何在 C# 中的 Dictionary 中制作字典的深层副本? [复制]
【发布时间】:2013-06-30 21:16:37
【问题描述】:

我有四个 Dictionary ,两个是(字典中的字典),声明如下

    Dictionary<string, Dictionary<string, string>> dict_set = new Dictionary<string, Dictionary<string, string>>();
    Dictionary<string, Dictionary<string, string>> dict_Reset = new Dictionary<string, Dictionary<string, string>>();
    Dictionary<string, string> set_value = new Dictionary<string, string>();
    Dictionary<string, string> Reset_value = new Dictionary<string, string>();

我想先在字典 set_vlaue 和 Reset_value 中添加元素。 添加值后,我会将这些字典添加到其他两个字典中,如下所示。

dict_set.Add(condiName, set_value);
dict_Reset.Add(condiName, Reset_value);
 set_value.Clear();
 Reset_value.Clear();

值正在被添加,但是在添加 set_value 和 reset_value 字典之后,我想清除这两个字典 set_value 和 reset_value,但是当 set_value 和 reset_value 被清除时,dict_set 和 dict_reset 中的数据也被清除..

任何人都可以帮助我,在这种情况下如何创建字典的深层副本...

【问题讨论】:

  • 在这里查看 Jon Skeet 的回答 stackoverflow.com/questions/139592/…
  • @keyboardP 实际上我想在执行以下操作时制作字典的深层副本.. dict_set.Add(condiName, set_value); dict_Reset.Add(condiName, Reset_value);一完成我想清除set_value和reset_value..以便可以添加新值..但是根据您的代码,如果我在添加之前克隆它们,一个键将具有其他键数据..
  • @KeyboardP:Skeet 回答的一个问题是它执行叶子的“克隆”副本,这不能保证深度复制。这里的作者想要一个深刻的,所以这不是完全重复的。仍然使用 Skeet 的答案,很容易找到解决方案。
  • 另请注意,Skeet 在第一条评论中链接的主题中有 两个 答案。

标签: c# winforms c#-4.0


【解决方案1】:

我不知道您要在工作流程中做什么,但为什么不重新实例化而不是清理?

dict_set.Clear(); 

到:

dict_set = new Dictionary<string, string>(); 

【讨论】:

  • 实际上 set_value 和 reset_value 字典将临时值存储在循环一中,工作结束了,我想清除它们,以便在下一次迭代中这些值将具有新值..
  • 如果我理解正确,您希望将值从 set_/reset_value 字典复制到 dict_set/_reset 字典,而不是清理 set_/reset_value 字典。所以:不要在循环中使用“set_/reset_value.Clear()”,使用“set_/reset_value = new ...”
  • 顺便说一句:你可以从 dict_set.Add(condiName, set_value); dict_Reset.Add(condiName, Reset_value);到 dict_set.Add(condiName, new Dictionary(set_value)); dict_Reset.Add(condiName, new Dictionary(Reset_value));
  • 每次都创建新实例是个好主意吗?它将在内存中创建多个实例。
  • @mcjoin 每次创建新实例都可以解决我的问题,但不知道这是否是一个好的解决方案..
【解决方案2】:

除了 Skeet 在keyboardP 指出的答案中所写的内容外,在大多数托管语言中,您可以通过以下方式轻松执行深层复制:

  • 序列化事物
  • 反序列化它

反序列化后,您通常会获得原始文件的完整深层克隆。序列化程序通常会执行所有 ID 检查、中断循环、重复数据删除等。在您的情况下,这不是必需的,但以后可能会派上用场。

您可以将其序列化为 XML、BinaryForm、JSON 或任何您喜欢和手头的东西。没那么重要。

现在回到你的问题:

这是你的代码,只是缩短了一点:

var dict_set = new Dictionary<string, Dictionary<string, string>>();
var dict_Reset = new Dictionary<string, Dictionary<string, string>>();
var set_value = new Dictionary<string, string>();
var Reset_value = new Dictionary<string, string>();

dict_set.Add(condiName, set_value);
dict_Reset.Add(condiName, Reset_value);

set_value.Clear();
Reset_value.Clear();

您声称:

(...) 但是会出现问题,当 set_value 和 reset_value 被清除时,dict_set 和 dict_reset 中的数据也会被清除..

不是真的。使用上面的代码,这是不可能。 set/reset/dict_set/dict_reset 是 4 个不同的对象。在“设置/重置”上调用“清除”不会导致其他的被清除

查看您的代码。错误在别处。不在这里。其他东西正在清除 dict* 字典。

【讨论】:

  • 清除set_value.Clear()后; Reset_value.Clear();应该在 dict_set 和 dict_reset 中的数据丢失了.. 只有存在的内容是键名,即 condiname,实际上 dict_set 和 dict_reset 是字典中的字典..
【解决方案3】:

通过创建新实例将解决上述问题..如果有人遇到其他更好的解决方案,请发布..

     dict_set.Add(condiName, new Dictionary<string, string>(set_value));
     dict_Reset.Add(condiName, new Dictionary<string, string>(Reset_value)); 
     set_value.Clear();
     Reset_value.Clear();

【讨论】:

    【解决方案4】:

    我认为这样 dict_set 和 dict_Reset 中的内部字典不会被清除

    dict_set.Add(condiName, set_value.ToDictionary(entry => entry.Key,entry => entry.Value));
    dict_Reset.Add(condiName, Reset_value.ToDictionary(entry => entry.Key,entry => entry.Value));
    set_value.Clear();
    Reset_value.Clear();
    

    使用 ToDictionary() 方法,您实际上创建了一个新的 Dictionary 对象,不再使用对旅游原件词典的引用,因此您可以安全地清除它们。 向 set_value 和 Reset_value 添加和删除数据也不会影响 dict_set 和 dict_Reset 中的字典

    只是出于好奇,为什么 Reset_value 带有大写的 S 而 set_value 不是?

    【讨论】:

    • 好的,你复制粘贴一遍代码,set_value 和 dict_set 大写.. :)
    猜你喜欢
    • 1970-01-01
    • 2017-06-23
    • 1970-01-01
    • 2016-01-29
    • 1970-01-01
    • 2011-10-25
    • 1970-01-01
    • 2015-12-28
    相关资源
    最近更新 更多