3

I am using a dictionary within a dictionary. The last key value assigned is getting stored as values for all previous keys as well, even though the individual key assignments are different. Am I missing something?

Dictionary<string, Dictionary <int,bool>> seenValsRounds= new Dictionary<string, Dictionary<int, bool>>();

void prepareRoundsVals()
    {       
        Dictionary <int,bool> roundVals = new Dictionary<int, bool> ();
        roundVals.Add (0,false);
        seenValsRounds.Add ("A", roundVals);
        seenValsRounds.Add ("B", roundVals);
        seenValsRounds.Add ("C", roundVals);
        seenValsRounds.Add ("D", roundVals);
        seenValsRounds ["A"] [0] = false;
        seenValsRounds ["B"] [0] = false;
        seenValsRounds ["C"] [0] = false;
        seenValsRounds ["D"] [0] = true;
        foreach (KeyValuePair<string, Dictionary<int,bool>> kvp in seenValsRounds) {            
            Debug.Log(kvp.Key + " in round " + 0 + ": " + seenValsRounds [kvp.Key][0]);     
        }
    }

Expected Results: A is false, B is false, C is false, D is True

Actual Results: A is True, B is True, C is True, D is True


Solved below as per suggestions from answers and comments. Each nested dictionary should also be 'new':

        Dictionary <int,bool> roundVals1 = new Dictionary<int, bool> ();
        Dictionary <int,bool> roundVals2 = new Dictionary<int, bool> ();
        Dictionary <int,bool> roundVals3 = new Dictionary<int, bool> ();
        Dictionary <int,bool> roundVals4 = new Dictionary<int, bool> ();
        roundVals1.Add (0,false);
        roundVals2.Add (0,false);
        roundVals3.Add (0,false);
        roundVals4.Add (0,false);
        seenValsRounds.Add ("A", roundVals1);
        seenValsRounds.Add ("B", roundVals2);
        seenValsRounds.Add ("C", roundVals3);
        seenValsRounds.Add ("D", roundVals4);
double-beep
  • 5,031
  • 17
  • 33
  • 41
Bhrigu
  • 88
  • 10
  • 3
    You are adding the same Dictionary, roundVals, four times, to seensValsRounds. In your code, there are only two different Dictionaries at play, since you are only doing two "new". – Dan Byström May 07 '19 at 13:18
  • You have one object. you put in in different box. Paint this object in green. The green object can be find in any of those box. – xdtTransform May 07 '19 at 13:24
  • There must be a dupe about ref type and value type somewhere with a basic List – xdtTransform May 07 '19 at 13:26
  • [Eric Lippert gave a great answer](https://stackoverflow.com/a/9203760/91) explaining references in C#, which is what you're running into here. I'm not sure what the best approach for your issue is (e.g., maybe refactor the nested dictionary into something else? Or just clone/copy the Dictionaries as needed), but the root cause is that Dictionary is a reference type. – Michael Stum Jun 22 '21 at 14:59

2 Answers2

3

Thats because you put the same reference to the roundVals dictionary object in the seenValsRounds dictionary. You should create a new dictionary for A, B, C and D.

D.W
  • 300
  • 2
  • 13
0

It's may be helpful or Nested dictionary alternative.

Create Sample.cs script and test it.

 public Dictionary<string,Tuple<string,string,string,int>> _planets = new 
     Dictionary<string, Tuple<string,string, string, int>>();
     void Start()
     {
           string myKey = string.Concat("1","MetalMine","Level");
           if(!_planets.ContainsKey(myKey))
           {
               _planets.Add(myKey,Tuple.Create("1","MetalMine","Level",0));
           }
           Debug.Log("_planets mykey "+myKey+" ==> "+_planets[myKey].Item4);
     }
Atul Patel
  • 71
  • 2