2

I have some code that uses the GetOrAdd function from ConcurrentDictionary to add values with a unique key to a holder. However, I want to be able to tell if a values key is found (i.e. a true returned from TryGet) or whether it has to be added.

I haven't been able to find anything online that suggests this is achievable so if anyone has any ideas it would be really helpful.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Sam
  • 21
  • 1
  • You need to run TryGet. Then when you have old value you can compare with the value returned from GetOrAdd. GetOrAdd returns following : The value for the key. This will be either the existing value for the key if the key is already in the dictionary, or the new value for the key as returned by valueFactory if the key was not in the dictionary. – jdweng Jun 09 '23 at 11:30
  • 1
    What [`GetOrAdd`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentdictionary-2.getoradd) overload are you using? The one with parameter `value` or the other with parameter `valueFactory`? – Theodor Zoulias Jun 09 '23 at 11:57
  • 2
    Although it is not required, it might be interesting to include in the question the reason that you need this feature. What difference does it make if the key already existed, or it was just inserted? I can't think of a scenario where this difference matters. – Theodor Zoulias Jun 09 '23 at 12:01
  • 1
    Doesn't [TryAdd](https://learn.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentdictionary-2.tryadd?view=net-7.0) do what you want already? What's the actual problem and why aren't the current methods enough? Are you looking for a `TryAdd` that generates the value lazily, the way `GetOrAdd(,Func)` does? – Panagiotis Kanavos Jun 09 '23 at 12:14
  • As @PanagiotisKanavos says, there's `TryOrAdd`. If construction is expensive, consider changing your dictionary from being a `ConcurrentDictionary` to being a `ConcurrentDictionary>`. `Lazy` doesn't add much overhead if it's already had to produce its value and you can control concurrency in construction better. – Damien_The_Unbeliever Jun 09 '23 at 13:14
  • @Damien_The_Unbeliever that assumes that lazy generation is indeed a requirement. Perhaps the real question is knowing whether the value is "new"? Why would that matter? Unless someone is trying to filter duplicate messages by ID? The actual value doesn't matter then, and `TryAdd` is enough. – Panagiotis Kanavos Jun 09 '23 at 13:26

1 Answers1

0

Not consistently, no. If the method returns something other than the value that you provide then you know that the key already existed but if the key exists and has the same value that you provide then there will be no distinction. If you want to know definitively then you will have to test for the key first. It sounds like your best bet is to call ContainsKey first and then call GetOrAdd. You could wrap that into your own single method so it's easy to reuse and lock the dictionary if you need it to be atomic.

jmcilhinney
  • 50,448
  • 5
  • 26
  • 46