Reputation: 457
I basically have a list of Dictionaries like:
List<Dictionary<string, string>>
For the purposes of testing I'm fetching 36 dictionary items into the list and then returning the list at the end of my function.
The odd thing is when I populate the list, I can see the Key=>Value pairs of the dictionaries being added to the list in the Visual Studio Inspector, however upon clearing the original dictionary used to populate my list, all that remains is 36 empty items in the list.
Is there some weird List behaviour happening that I'm unaware of? A code snip is included below for reference...
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;
Upvotes: 4
Views: 5692
Reputation: 216273
You add the same INSTANCE of dictionary in the list for every loop.
It is only expected that when you clear the dictionary every one is emptied
to resolve the problem you need to add this to your cycle
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);
}
However I need to ask you. Why to use a dictionary to store columns and rows? You could achieve your result with a DataTable
DataTable dt = new DataTable();
dt.Load(dataReader);
and forget the List and the Dictionary
Upvotes: 5
Reputation: 203811
As others have said, when you add the dictionary to the list you are only adding an additional reference to the same existing dictionary. That said, I'd suggest a different solution than copying it.
The problem is that your dictionary is at the top level of scope. It shouldn't be. You're trying to re-use the same dictionary over and over. You'll be better off simply defining the dictionary at a lower level, inside of the while
loop:
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();
}
//...
Note the only change I made was moving the declaration of selectResult
.
By creating a new dictionary for each iteration of the while
loop you ensure that you're adding a new dictionary each time.
Upvotes: 0
Reputation: 99859
You are adding a reference to the Dictionary
to your list, so changes in the original dictionary are also reflected in the instances you access through the list. If you want to add a copy of the Dictionary
, you'll need to use something like this:
allResults.Add(new Dictionary<string, string>(selectResult));
Upvotes: 0
Reputation: 40818
Dictionary
is a reference type. You need to make a new one: selectResult = new Dictionary<string, string>()
instead of calling Clear
.
Upvotes: 0
Reputation: 4353
Because you did not clone it. And you copied the address of the first object. Use clone next time.
Upvotes: 2