3

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

List<Dictionary<string, string>>

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

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

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

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

5 回答 5

4

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

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

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

忘记列表和字典

于 2013-03-22T15:52:39.523 回答
2

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

深度克隆对象

于 2013-03-22T15:51:58.793 回答
0

Dictionary是引用类型。您需要创建一个新的:selectResult = new Dictionary<string, string>()而不是调用Clear.

于 2013-03-22T15:52:44.427 回答
0

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

allResults.Add(new Dictionary<string, string>(selectResult));
于 2013-03-22T15:53:51.097 回答
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您可以确保每次都添加一个新字典。

于 2013-03-22T15:59:38.697 回答