Dictionary Vs Concurrent Dictionary in .NET 8
Well we all know that a dictionary in C# is a generic collection that can be used to store key/value pairs, where each key is unique within the dictionary, and it maps to a specific value. But when we come to know that concurrent dictionary is also a thing then most of us got confused between dictionary and concurrent dictionary. So in this article we will understand the difference between dictionary and concurrent dictionary, also we will talk about that in which scenario you should use standard dictionary and when you should use concurrent dictionary.
What is Dictionary?
A dictionary is essentially a generic collection of key-value pairs, where each key corresponds to a unique value. You can draw an analogy between a dictionary in programming and a real-world dictionary, where you look up a word (key) to find its definition (value).
The `Dictionary<TKey, TValue>` class in .NET allows you to define both the data type for keys (`TKey`) and the data type for values (`TValue`). For instance, you can create a dictionary with integers as keys and strings as values, denoted as `Dictionary<int, string>`. It provides a structured way to organize and retrieve data.
It's important to note that in a `Dictionary`, keys must be unique, ensuring that each key is associated with a single value. Additionally, keys should not be null for reference types. On the other hand, values can be null, especially if they are of a reference type.
What is Concurrent Dictionary?
A `ConcurrentDictionary` is a thread-safe collection of key-value pairs, providing a mechanism for multiple threads to access and modify the data concurrently while ensuring data integrity. This class is specifically designed to handle scenarios where multiple threads might simultaneously access, add, or modify entries in the dictionary.
The primary goal of the `ConcurrentDictionary<TKey, TValue>` class is to prevent race conditions, a common issue that arises when two or more threads attempt to access and modify shared data simultaneously. Race conditions can lead to unpredictable behavior, including data corruption, incorrect results, or exceptions.
What you should use Dictionary and when Concurrent Dictionary?
ConcurrentDictionary is primarily for use in an environment where you're updating the dictionary from multiple threads (or async tasks). You can use a standard Dictionary from as much code as you like if it's from a single thread.
If you look at the methods on a ConcurrentDictionary, you'll spot some interesting methods like TryAdd, TryGetValue, TryUpdate, and TryRemove.
For example, consider a typical pattern you might see for working with a normal Dictionary class.
if (!dictionary.ContainsKey(id))
dictionary.Add(id, value);This has an issue in that between the check for whether it contains a key and calling Add a different thread could call Add with that same id. When this thread calls Add, it'll throw an exception. The method TryAdd handles that for you and will return a true/false telling you whether it added it (or whether that key was already in the dictionary).
So unless you're working in a multi-threaded section of code, you probably can just use the standard Dictionary class. That being said, you could theoretically have locks to prevent concurrent access to a dictionary.
Real-World Use Case of a Dictionary: Based on My Experience
In a project I worked on, I stored unique device IDs from mobile devices in a standard dictionary. All API calls were asynchronous, and upon receiving a request, I checked whether the device ID existed in the standard dictionary. If it did, I approved the request; otherwise, I fetched the device ID from the database and stored it in the dictionary.
However, I encountered a wired issue where, at times, the mobile client would throw an ArgumentException stating "Item with the same key has already been added." To address this issue, I replaced the standard dictionary with a concurrent dictionary. This change resolved the problem, ensuring that concurrent access to the dictionary by multiple threads did not result in key conflicts or exceptions. The concurrent dictionary provided the necessary thread safety, preventing simultaneous additions or modifications to the dictionary from causing errors.


