C#清除原始对象时,为什么我的列表项被清空?

时间:2013-03-22 15:50:20

标签: c# list dictionary

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

List<Dictionary<string, string>>

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

奇怪的是,当我填充列表时,我可以看到在Visual Studio Inspector中添加到列表中的字典的Key =&gt;值对,但是在清除用于填充列表的原始字典时,所有剩下的就是列表中的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;

5 个答案:

答案 0 :(得分:4)

在每个循环的列表中添加相同的字典INSTANCE 只有当您清除字典时才会预期每个字体都被清空

解决您需要将此问题添加到周期中的问题

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

并忘记列表和词典

答案 1 :(得分:2)

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

Deep cloning objects

答案 2 :(得分:0)

Dictionary是参考类型。您需要制作一个新代码:selectResult = new Dictionary<string, string>(),而不是调用Clear

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

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

问题是你的词典处于最高级别。它不应该。你试图一遍又一遍地重复使用同一个字典。你最好只在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循环的每次迭代创建一个新字典,确保每次都添加一个新字典。