Does adding a new dictionary key-value removes other elements?

This is so embarrassing. Here’s my dictionary:

private Dictionary<int, List<IExplosionDamageGiver>> m_DeployedExplosiveMap = new Dictionary<int, List<IExplosionDamageGiver>>();

The key is a unique ID(using Photon’s ViewID) and the value is a list of IExplosionDamageGiver objects.

Here’s the code for adding the actual value into the dictionary:

print("Deployer: " + deployerViewID);
print("Contains Deployer: " + m_DeployedExplosiveMap.ContainsKey(deployerViewID));

if (m_DeployedExplosiveMap.ContainsKey(deployerViewID) == false) {
    print("Create List for " + deployerViewID);
    m_DeployedExplosiveMap.Add(deployerViewID, new List<IExplosionDamageGiver>());

    print("Current Keys: " + m_DeployedExplosiveMap.Keys.Count);

    foreach (var item in m_DeployedExplosiveMap) {
        print("Key: " + item.Key + ", Count: " + item.Value.Count);
    }
}
else {
    print("List for " + deployerViewID + " is already exists");
}

m_DeployedExplosiveMap[deployerViewID].Add(damageGiver);
print("Deployed Count: " + m_DeployedExplosiveMap[deployerViewID].Count);

If there’s no key in the dictionary, create a new key-value pair then use [ ] to update the value. Value is a list and used List.Add add new item to the list.

Here’s the logs trying deployerViewID 2001:

Deployer: 2001
Contains Deployer: False
Create List for 2001
Current Keys: 1
Key: 2001, Count: 0
Deployed Count: 1

Running the same logic with the same deployerViewID 2001 works fine. Dictionary has 1 key, and the value List is keep adding a new element.

However, when the same logic with a different deployerViewID 1003 causes weird results. I expected that the key 1003 didn’t exist in the dictionary so created a new key-value pair, and put the object in the just-created List for ID 1003, but it wasn’t. Instead, it ERASES the key-value for deployerViewID 2001. It just gone.

Deployer: 1003
Contains Deployer: False
Create List for 1003 // -> Works as expected. New int, List pair created.
Current Keys: 1 // WTF? Why dictionary have 1 key? It is supposed to be 2 keys!!
Key: 1003, Count: 0
Deployed Count: 1

I used foreach to iterate the dictionary but key 2001 and its value it’s just gone. Is this how the Dictionary works in C#? I used the same this way into many different game logics but none of them had this issue. Only this code makes trouble.

Seriously there’s no extra code that accesses the dictionary. That’s the all code. Is this a glitch or is my knowledge is wrong? Can anyone please explain to me what the heck is going on?

Since adding to a dictionary doesn’t remove previous entries, the first things I would check is to make sure you aren’t recreating the dictionary.

If the following code is called multiple times, it overwrites it and creates a new instance of the dictionary. Thus, it would appear to “empty” itself.

m_DeployedExplosiveMap = new Dictionary<string, List<IExplosionDamageGiver>();

The next thing is to make sure you are trying to store values in the same instance of the dictionary. If you have multiple instances of the script, each one might have it’s own dictionary.

And of course, just make sure there isn’t anything that is removing previous entries or clearing the dictionary.

Either way, the act of simply adding to a dictionary does not clear the dictionary.

A cleaner, more readable, more robust approach:

// We mark the field as readonly to make sure we're creating the dictionary only once!
private readonly Dictionary<int, List<IExplosionDamageGiver>> m_DeployedExplosiveMap = new();
// We create a function that takes care of lists creation
private List<IExplosionDamageGiver> GetOrCreateExplosionDamageGiverList(string key)
{
    if (!m_DeployedExplosiveMap.TryGetValue(key, out var list) || list == null)
    {
        list = new List<IIExplosionDamageGiver>();
        m_DeployedExplosiveMap[key] = list;
    }

    return list;
}
// We call the above function when we need to get a list
var list = GetOrCreateExplosionDamageGiverList(key);

// We have now a reference to the list, let's just use it!
list.Add(damageGiver);

In which script does that “m_DeployedExplosiveMap” variable actually live in? Do you only have a single instance of that script? If not each instance will have it’s own dictionary. In 99% of all cases when a list, variable, array or dictionary suddenly seems to be empty even though you added / assigned a value, the reason is that you have more than one instance and your adding / reading happens on different instances.

We don’t really have a full picture since we don’t even know the name of the script which might have given a clue.