When initializing a new ConcurrentDictionary starting from an existing ConcurrentDictionary, the new object will act as pointer.
// Summary:
// Initializes a new instance of the System.Collections.Concurrent.ConcurrentDictionary`2
// class that contains elements copied from the specified System.Collections.Generic.IEnumerable`1,
// has the default concurrency level, has the default initial capacity, and uses
// the default comparer for the key type.
public ConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection);
based on this description I wrote the following code:
public static ConcurrentDictionary<int, myCustomClass> startDictionary;
[...]
ConcurrentDictionary<int, myCustomClass> tempDictionary =
new ConcurrentDictionary<int, myCustomClass>(startDictionary);
because i need to modify some data into tempDictionary without affecting startDictionary.
What happens is that any edit to tempDictionary is reflected to startDictionary too. Am I doing something wrong?
Can you share a repro? I don't see how that's possible. Adds/removes/etc. to startDictionary should definitely not be visible to tempDictionary. But if TKey/TValue are classes and you mutate those instances, then yeah, as with any collection, the updates would be visible to both collections, because they're both storing the original object.
For example, if you write:
```C#
class C
{
public int Value;
}
...
var c1 = new C() { Value = 42 };
var c2 = new C() { Value = 42 };
var oldList = new List
oldList.Add(c1);
var newList = new List
newList.Add(c2);
oldList will contain only c1 and newList will contain both c1 and c2. If you then do:
```C#
c1.Value = 84;
then both oldList and newList will still contain c1, which will have a Value of 84.
Share the repo is difficult because you would need my db and so on to have it running.
i have
class myCustomClass
{
public int Id;
public int value1;
public int value2;
}
[...]
public static ConcurrentDictionary<int, myCustomClass> startDictionary =
new ConcurrentDictionary<int, myCustomClass>();
private void myMethod()
{
var mCC = new myCustomClass(){ Id = 1, value1 = 1, value2 = 3 };
startDictionary.TryAdd(1, mCC); // startDictionary receives data
}
[...]
ConcurrentDictionary<int, myCustomClass> tempDictionary =
new ConcurrentDictionary<int, myCustomClass>(startDictionary ); // my temp Dict to be modified
foreach (myCustomClass mcc in tempDictionary.Values) // <-- THIS
{
mcc.value2 = Id + value1; // Just for example
}
// tempDictionary[1].value2 is now == 2
// startDictionary[1].value2 is now == 2 <-- NOT GOOD (for me)
DoThingsWithModified(tempDictionary);
What i don't understand is why the foreach // <-- THIS is affecting startDictionary too. Is it normal?
Is it normal
Yes. You're not modifying the dictionary. You're modifying an object stored in the dictionary. When you copy the dictionary, you're copying over all of the object references the dictionary contains... if you change that referenced object, that change will be visible everywhere, because it's the same object both dictionaries contain. This is the same as the c1.Value change in my previous response.
AKA shallow-copy semantics (when you were expecting some form of deep copy).
Uhm, i understand..
Could you kindly suggest a different approach to my needing?
The only idea i have is
ConcurrentDictionary<int, myCustomClass> tempDictionary =
new ConcurrentDictionary<int, myCustomClass>(); // no reference to startDictionary
foreach (KeyValuePair<int, myCustomClass> kvp in startDictionary)
{
myCustomClass mcc = new myCustomClass()
{
Id = kpv.Value.Id,
value1 = kvp.Value.value1,
value2 = kvp.Value.value2
};
tempDictionary.TryAdd(kvp.Key, mcc);
}
foreach (myCustomClass mcc in tempDictionary.Values)
{
mcc.value2 = Id + value1; // Just for example
}
DoThingsWithModified(tempDictionary);
but, I'm not sure this would solve my problem...
Your approach is fine: you're cloning the object to add to the second dictionary so that it's not the same object as the one stored in the first dictionary.