To fix compiler error you can do this:
myDic.AddOrUpdate(1, new HashSet<int>() { myFirstElement },
(key, actualValue) => {
actualValue.Add(myFirstElement);
return actualValue;
});
BUT this is not thread safe, because "update" function is not run inside any lock so you are potentially adding to not-thread-safe HashSet
from multiple threads. This might result in (for example) losing values (so you were adding 1000 items to HashSet
but in the end you have only 970 items in it for example). Update function in AddOrUpdate
should not have any side effects and here it does.
You can lock yourself over adding values to HashSet
:
myDic.AddOrUpdate(1, new HashSet<int>() { myFirstElement },
(key, actualValue) => {
lock (actualValue) {
actualValue.Add(myFirstElement);
return actualValue;
}
});
But then question is why you are using lock-free structure (ConcurrentDictionary
) in the first place. Besides that - any other code might get HashSet
from your dictionary and add value there without any locks, making the whole thing useless. So if you decide to go that way for some reason - you have to ensure that all code locks when accessing HashSet
from that dictionary.
Instead of all that - just use concurrent collection instead of HashSet
. There is no ConcurrentHashSet
as far as I know but you can use another ConcurrentDictionary
with dummy keys as a replacement (or look over internet for custom implementations).
Side note. Here
myDic.AddOrUpdate(1, new Hashset<int>(){myFirstElement},
you create new HashSet
every time when calling AddOrUpdate
, even if that dictionary is not needed because key is already there. Instead use overload with add value factory:
myDic.AddOrUpdate(1, (key) => new HashSet<int>() { myFirstElement },
Edit: sample usage of ConcurrentDictionary
as hash set:
var myDic = new ConcurrentDictionary<long, ConcurrentDictionary<int, byte>>();
long key = 1;
int element = 1;
var hashSet = myDic.AddOrUpdate(key,
_ => new ConcurrentDictionary<int, byte>(new[] {new KeyValuePair<int, byte>(element, 0)}),
(_, oldValue) => {
oldValue.TryAdd(element, 0);
return oldValue;
});