2013-03-22 56 views
3

我基本上有一個像字典的名單:C#爲什麼清理原始對象時我的清單項目被清空?

List<Dictionary<string, string>> 

對於我取36字典項到列表中,然後在我的函數的端返回的列表中的測試目的。

奇怪的是,當我填充列表時,我可以看到在Visual Studio Inspector中添加到列表中的字典的Key => Value對,但是在清除用於填充我的列表的原始字典時,所有仍然是列表中的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; 

回答

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

實現你的結果,忘記了列表和字典

+0

真的沒有什麼好的理由在'while'循環之外定義字典。它只意味着你可能會忘記重新初始化它,或者在循環的範圍之前/之後使用它,它只是沒有意義被使用。如果你在循環中定義它,你確保它每次都被編譯器初始化,並確保它不能用在其它沒有意義的上下文中。 – Servy 2013-03-22 16:00:59

+0

是的,我同意並修復答案,但是我仍然對這種數據表的改造感到困惑。 – Steve 2013-03-22 16:03:12

+0

噢,現在我的答案和你的答案是一樣的...... – Steve 2013-03-22 16:05:32

2

因爲您沒有克隆它。並且您複製了第一個對象的地址。 下一次使用克隆。

Deep cloning objects

0

Dictionary是引用類型。您需要創建一個新的:selectResult = new Dictionary<string, string>()而不是調用Clear

0

您正在爲列表添加對Dictionary的引用,以便原始字典中的更改也反映在您通過列表訪問的實例中。如果您要添加的Dictionary副本,你需要使用這樣的事情:

allResults.Add(new Dictionary<string, string>(selectResult)); 
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循環的每次迭代創建一個新字典,確保您每次都添加一個新的字典。