【问题标题】:C# issue with dictionarys字典的 C# 问题
【发布时间】:2019-07-14 04:08:12
【问题描述】:

我写了如下代码结构:

public Dictionary<string, Dictionary<string, Object>> file_data = new Dictionary<string, Dictionary<string, Object>>();

public Form1()
{
    InitializeComponent();

    Dictionary<string, Object> temporary = new Dictionary<string, Object>();
    temporary.Add("content", null);
    temporary.Add("droplist", false);
    temporary.Add("valid_file", false);
    file_data.Add("base_data", temporary);
    file_data.Add("supplier_data_1", temporary);
    file_data["base_data"]["droplist"] = true;
    MessageBox.Show(file_data["supplier_data_1"]["droplist"].ToString());
}

我只是想更新["base_data"]["droplist"],但代码也更新了["supplier_data_1"]["droplist"] 值(消息框显示为真)。为什么这样做?我必须如何调整 file_data["base_data"]["droplist"] 将仅更改的代码? Dictionary 必须保持其结构。

【问题讨论】:

  • base_data 和supplier_data_1 指向同一个字典。您可以通过 file_data.Add("supplier_data_1", new Dictionary&lt;string, object&gt;(temporary)); 使供应商数据 1 指向字典的单独副本

标签: c# dictionary


【解决方案1】:

Object 是一个引用类型。 Microsoft Value Types post有很好的解释

值类型的变量包含该类型的值。例如,int 类型的变量可能包含值 42。这与引用类型的变量不同,引用类型的变量包含对该类型实例的引用,也称为对象。当您将新值分配给值类型的变量时,会复制该值。当您为引用类型的变量分配新值时,复制的是引用,而不是对象本身。

你应该克隆那个字典。就像here 解释的那样。你可以这样做:

file_data.Add("supplier_data_1", CloneDictionary(temporary));

或者更好的是,基于第一个字典创建一个新字典。

file_data.Add("supplier_data_1", new Dictionary<string, object>(temporary));

【讨论】:

  • 我想知道,是什么让您相信在第一个字典的基础上创建一个新字典比克隆它甚至更好
  • 您必须克隆Dictionary&lt;string, object&gt; 中的所有object,否则对其中的任何引用类型的更改都会同时更改。
  • 基本上,因为您使用的是 .NET 内置代码,而不是编写自己的克隆代码。
  • 这是真的@MikaelDúiBolinder。但他在那里只使用值类型。但好点。在这种情况下,您将需要一个深度克隆算法。
  • 那么也许使用using ValueTypeDictionary = Dictionary&lt;string, ValueType&gt;?
【解决方案2】:

您将同一对象添加两次:

file_data.Add("base_data", temporary);
file_data.Add("supplier_data_1", temporary);

temporary 变量指向内存中的一个对象。现在字典中的两个引用也指向内存中的那个对象。但是内存中仍然只有 一个 对象。对该对象的任何更新都会被对该对象的任何引用看到。

为了在字典中有两个不同的对象,你需要创建第二个对象。您可以通过在代码中创建两个变量、填充每个变量并将它们添加到结果字典中来手动执行此操作。或者,如果它们都是简单的值类型,您也可以围绕相同的值创建一个新字典:

file_data.Add("supplier_data_1", temporary.ToDictionary(x => x.Key, x => x.Value));

【讨论】:

    【解决方案3】:

    正如@hardkoded 所说,它是a reference type

    // Here you define `temporal` object
    Dictionary<string, Object> temporary = new Dictionary<string, Object>();
    
    // Here you add a reference/pointer to the `temporal` object as values to these keys
    file_data.Add("base_data", temporary);
    file_data.Add("supplier_data_1", temporary);
    
    // When you get the values for the "base_data" and "supplier_data_1" keys, you get a refence to the `temporal`object.
    var baseData = file_data["base_data"];
    var supplierData1 = file_data["supplier_data_1"];
    
    // If you compare those variables, you'll find out that they are references to the same object!
    if (baseData == supplierData1) // true
        Debug.WriteLine("They are the same!");
    

    因此,对file_data["base_data"] 所做的任何更改都将应用于file_data["supplier_data_1"],因为它们当前是指向同一对象的引用/指针!

    【讨论】:

      猜你喜欢
      • 2013-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-15
      • 2020-11-13
      • 1970-01-01
      相关资源
      最近更新 更多