【问题标题】:C# Why are my list items being emptied when I clear the original object?C#为什么当我清除原始对象时我的列表项被清空?
【发布时间】:2013-03-22 15:50:20
【问题描述】:

我基本上有一个字典列表,例如:

List<Dictionary<string, string>>

出于测试目的,我将 36 个字典项提取到列表中,然后在函数结束时返回列表。

奇怪的是,当我填充列表时,我可以看到字典的 Key=>Value 对被添加到 Visual Studio Inspector 的列表中,但是在清除用于填充我的列表的原始字典后,所有这些剩下的是列表中的 36 个空项。

是否发生了一些我不知道的奇怪的 List 行为?下面包含一个代码片段以供参考...

    List<Dictionary<string, string>> allResults = new List<Dictionary<string, string>>();
    Dictionary<string, string> selectResult = new Dictionary<string, string>();

    MySqlCommand cmd = new MySqlCommand(query, conn);
    MySqlDataReader dataReader = cmd.ExecuteReader();

    try
    {
        while (dataReader.Read())
        {
            for (int i = 0; i < dataReader.FieldCount; i++)
            {
                selectResult.Add(dataReader.GetName(i).ToString(), dataReader.GetValue(i).ToString());
            }
            allResults.Add(selectResult);

            //Something to do with this next line seems to cause the List to also lose the values stored in the Dictionary, is clearing the dictionary not allowed at this point and the list is simply referencing the Dictionary rather than 'making a copy'?
            selectResult.Clear();
        }
        dataReader.Close();
    }

    catch { }

    this.Close();

    return allResults;

【问题讨论】:

    标签: c# list dictionary


    【解决方案1】:

    您在列表中为每个循环添加相同的字典实例。
    只希望当您清除字典时,每个都清空

    要解决问题,您需要将此添加到您的循环中

       while (dataReader.Read())
       {
            // at every loop, create a new instance of dictionary using the same variable
            Dictionary<string,string> selectResult = new Dictionary<string, string>();
            for (int i = 0; i < dataReader.FieldCount; i++)
            {
                selectResult.Add(dataReader.GetName(i).ToString(), dataReader.GetValue(i).ToString());
            }
            // Adding a different copy of the dictionary in the list
            allResults.Add(selectResult);
        }
    

    但是我需要问你。为什么要使用字典来存储列和行? 您可以使用 DataTable 实现您的结果

        DataTable dt = new DataTable();
        dt.Load(dataReader);
    

    忘记列表和字典

    【讨论】:

    • 根本没有任何充分的理由在while 循环之外定义字典。这仅意味着您可能会忘记重新初始化它或在循环范围之前/之后使用它,在这种情况下使用它是没有意义的。如果你在循环中定义它,你确保它每次都被编译器初始化,并确保它不能在其他没有意义的上下文中使用。
    • 是的,我同意并修正了答案,但是我仍然对数据表的这种重新发明感到困惑。
    • C# 不是我常用的编码语言,所以一些更复杂的行为直到现在都避开了我,谢谢大家的回答,他们都很好地解释了我哪里出错了。将这个标记为正确,因为我使用了这个答案,并且它也提供了进一步思考的食物,因为我以前没有听说过数据表。
    【解决方案2】:

    因为你没有克隆它。你复制了第一个对象的地址。 下次使用克隆。

    Deep cloning objects

    【讨论】:

      【解决方案3】:

      Dictionary 是一个引用类型。你需要新建一个:selectResult = new Dictionary&lt;string, string&gt;(),而不是调用Clear

      【讨论】:

        【解决方案4】:

        您正在向列表中添加对Dictionary 的引用,因此原始字典中的更改也会反映在您通过列表访问的实例中。如果您想添加Dictionary副本,则需要使用以下内容:

        allResults.Add(new Dictionary<string, string>(selectResult));
        

        【讨论】:

          【解决方案5】:

          正如其他人所说,当您将字典添加到列表中时,您只是添加了对同一现有字典的附加引用。也就是说,我会建议一个不同于复制它的解决方案。

          问题是您的字典处于顶级范围。不应该。你试图一遍又一遍地重复使用同一个字典。最好在 while 循环内简单地定义字典:

          List<Dictionary<string, string>> allResults = new List<Dictionary<string, string>>();
          
          MySqlCommand cmd = new MySqlCommand(query, conn);
          MySqlDataReader dataReader = cmd.ExecuteReader();
          
          try
          {
              while (dataReader.Read())
              {
                  Dictionary<string, string> selectResult = new Dictionary<string, string>();
                  for (int i = 0; i < dataReader.FieldCount; i++)
                  {
                      selectResult.Add(dataReader.GetName(i).ToString(), dataReader.GetValue(i).ToString());
                  }
                  allResults.Add(selectResult);
              }
              dataReader.Close();
          }
          //...
          

          请注意,我所做的唯一更改是移动 selectResult 的声明。

          通过为while 循环的每次迭代创建一个新字典,您可以确保每次都添加一个新字典。

          【讨论】:

            猜你喜欢
            • 2016-09-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-07-13
            • 1970-01-01
            • 2022-11-15
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多