ConcurrentDictionary<TKey,TValue>.GetOrAdd Method
Definition
Important
Some information relates to prerelease product that may be substantially modified before it’s released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
Adds a key/value pair to the ConcurrentDictionary<TKey,TValue> if the key does not already exist. Returns the new value, or the existing value if the key already exists.
Overloads
GetOrAdd(TKey, Func<TKey,TValue>) |
Adds a key/value pair to the ConcurrentDictionary<TKey,TValue> by using the specified function if the key does not already exist. Returns the new value, or the existing value if the key exists. |
GetOrAdd(TKey, TValue) |
Adds a key/value pair to the ConcurrentDictionary<TKey,TValue> if the key does not already exist. Returns the new value, or the existing value if the key exists. |
GetOrAdd<TArg>(TKey, Func<TKey,TArg,TValue>, TArg) |
Adds a key/value pair to the ConcurrentDictionary<TKey,TValue> by using the specified function and an argument if the key does not already exist, or returns the existing value if the key exists. |
Examples
The following example shows how to call the GetOrAdd method:
class CD_GetOrAddOrUpdate
{
// Demonstrates:
// ConcurrentDictionary<TKey, TValue>.AddOrUpdate()
// ConcurrentDictionary<TKey, TValue>.GetOrAdd()
// ConcurrentDictionary<TKey, TValue>[]
static void Main()
{
// Construct a ConcurrentDictionary
ConcurrentDictionary<int, int> cd = new ConcurrentDictionary<int, int>();
// Bombard the ConcurrentDictionary with 10000 competing AddOrUpdates
Parallel.For(0, 10000, i =>
{
// Initial call will set cd[1] = 1.
// Ensuing calls will set cd[1] = cd[1] + 1
cd.AddOrUpdate(1, 1, (key, oldValue) => oldValue + 1);
});
Console.WriteLine("After 10000 AddOrUpdates, cd[1] = {0}, should be 10000", cd[1]);
// Should return 100, as key 2 is not yet in the dictionary
int value = cd.GetOrAdd(2, (key) => 100);
Console.WriteLine("After initial GetOrAdd, cd[2] = {0} (should be 100)", value);
// Should return 100, as key 2 is already set to that value
value = cd.GetOrAdd(2, 10000);
Console.WriteLine("After second GetOrAdd, cd[2] = {0} (should be 100)", value);
}
}
// Demonstrates:
// ConcurrentDictionary<TKey, TValue>.AddOrUpdate()
// ConcurrentDictionary<TKey, TValue>.GetOrAdd()
// ConcurrentDictionary<TKey, TValue>[]
// Construct a ConcurrentDictionary
let cd = ConcurrentDictionary<int, int>()
// Bombard the ConcurrentDictionary with 10000 competing AddOrUpdates
Parallel.For(
0,
10000,
fun i ->
// Initial call will set cd[1] = 1.
// Ensuing calls will set cd[1] = cd[1] + 1
cd.AddOrUpdate(1, 1, (fun key oldValue -> oldValue + 1)) |> ignore
)
|> ignore
printfn $"After 10000 AddOrUpdates, cd[1] = {cd[1]}, should be 10000"
// Should return 100, as key 2 is not yet in the dictionary
let value = cd.GetOrAdd(2, (fun key -> 100))
printfn $"After initial GetOrAdd, cd[2] = {value} (should be 100)"
// Should return 100, as key 2 is already set to that value2
let value2 = cd.GetOrAdd(2, 10000)
printfn $"After second GetOrAdd, cd[2] = {value2} (should be 100)"
' Imports System.Collections.Concurrent
' Imports System.Threading.Tasks
Class CD_GetOrAddOrUpdate
' Demonstrates:
' ConcurrentDictionary<TKey, TValue>.AddOrUpdate()
' ConcurrentDictionary<TKey, TValue>.GetOrAdd()
' ConcurrentDictionary<TKey, TValue>[]
Shared Sub Main()
' Construct a ConcurrentDictionary
Dim cd As New ConcurrentDictionary(Of Integer, Integer)()
' Bombard the ConcurrentDictionary with 10000 competing AddOrUpdates
Parallel.For(0, 10000,
Sub(i)
' Initial call will set cd[1] = 1.
' Ensuing calls will set cd[1] = cd[1] + 1
cd.AddOrUpdate(1, 1, Function(key, oldValue) oldValue + 1)
End Sub)
Console.WriteLine("After 10000 AddOrUpdates, cd[1] = {0}, should be 10000", cd(1))
' Should return 100, as key 2 is not yet in the dictionary
Dim value As Integer = cd.GetOrAdd(2, Function(key) 100)
Console.WriteLine("After initial GetOrAdd, cd[2] = {0} (should be 100)", value)
' Should return 100, as key 2 is already set to that value
value = cd.GetOrAdd(2, 10000)
Console.WriteLine("After second GetOrAdd, cd[2] = {0} (should be 100)", value)
End Sub
End Class
GetOrAdd(TKey, Func<TKey,TValue>)
- Source:
- ConcurrentDictionary.cs
- Source:
- ConcurrentDictionary.cs
- Source:
- ConcurrentDictionary.cs
Adds a key/value pair to the ConcurrentDictionary<TKey,TValue> by using the specified function if the key does not already exist. Returns the new value, or the existing value if the key exists.
public:
TValue GetOrAdd(TKey key, Func<TKey, TValue> ^ valueFactory);
public TValue GetOrAdd (TKey key, Func<TKey,TValue> valueFactory);
member this.GetOrAdd : 'Key * Func<'Key, 'Value> -> 'Value
Public Function GetOrAdd (key As TKey, valueFactory As Func(Of TKey, TValue)) As TValue
Parameters
- key
- TKey
The key of the element to add.
- valueFactory
- Func<TKey,TValue>
The function used to generate a value for the key.
Returns
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 if the key was not in the dictionary.
Exceptions
key
or valueFactory
is null
.
The dictionary contains too many elements.
Remarks
For modifications and write operations to the dictionary, ConcurrentDictionary<TKey,TValue> uses fine-grained locking to ensure thread safety. (Read operations on the dictionary are performed in a lock-free manner.) However, the valueFactory
delegate is called outside the locks to avoid the problems that can arise from executing unknown code under a lock. Therefore, GetOrAdd is not atomic with regards to all other operations on the ConcurrentDictionary<TKey,TValue> class.
Since a key/value can be inserted by another thread while valueFactory
is generating a value, you cannot trust that just because valueFactory
executed, its produced value will be inserted into the dictionary and returned. If you call GetOrAdd simultaneously on different threads, valueFactory
may be called multiple times, but only one key/value pair will be added to the dictionary.
The return value depends on the presence of the key in the dictionary and whether a key/value is inserted by another thread after GetOrAdd is called but before valueFactory
generates a value:
Scenario | Return value |
---|---|
The key is already in the dictionary. | The existing value is returned. |
The key is not in the dictionary. valueFactory generates a value. On rechecking for the key, no key is found. |
The key/value is inserted into the dictionary, and the value is returned. |
The key is not in the dictionary. valueFactory generates a value. While valueFactory is generating the value, a different thread inserts a value for the key. After valueFactory executes and upon rechecking for the key, the key inserted by the other thread is found. |
The value inserted by the other thread is returned. |
See also
Applies to
GetOrAdd(TKey, TValue)
- Source:
- ConcurrentDictionary.cs
- Source:
- ConcurrentDictionary.cs
- Source:
- ConcurrentDictionary.cs
Adds a key/value pair to the ConcurrentDictionary<TKey,TValue> if the key does not already exist. Returns the new value, or the existing value if the key exists.
public:
TValue GetOrAdd(TKey key, TValue value);
public TValue GetOrAdd (TKey key, TValue value);
member this.GetOrAdd : 'Key * 'Value -> 'Value
Public Function GetOrAdd (key As TKey, value As TValue) As TValue
Parameters
- key
- TKey
The key of the element to add.
- value
- TValue
The value to be added, if the key does not already exist.
Returns
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 if the key was not in the dictionary.
Exceptions
key
is null
.
The dictionary contains too many elements.
See also
Applies to
GetOrAdd<TArg>(TKey, Func<TKey,TArg,TValue>, TArg)
- Source:
- ConcurrentDictionary.cs
- Source:
- ConcurrentDictionary.cs
- Source:
- ConcurrentDictionary.cs
Adds a key/value pair to the ConcurrentDictionary<TKey,TValue> by using the specified function and an argument if the key does not already exist, or returns the existing value if the key exists.
public:
generic <typename TArg>
TValue GetOrAdd(TKey key, Func<TKey, TArg, TValue> ^ valueFactory, TArg factoryArgument);
public TValue GetOrAdd<TArg> (TKey key, Func<TKey,TArg,TValue> valueFactory, TArg factoryArgument);
member this.GetOrAdd : 'Key * Func<'Key, 'Arg, 'Value> * 'Arg -> 'Value
Public Function GetOrAdd(Of TArg) (key As TKey, valueFactory As Func(Of TKey, TArg, TValue), factoryArgument As TArg) As TValue
Type Parameters
- TArg
The type of an argument to pass into valueFactory
.
Parameters
- key
- TKey
The key of the element to add.
- valueFactory
- Func<TKey,TArg,TValue>
The function used to generate a value for the key.
- factoryArgument
- TArg
An argument value to pass into valueFactory
.
Returns
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 if the key was not in the dictionary.
Exceptions
key
is a null
reference (Nothing in Visual Basic).
The dictionary contains too many elements.
Remarks
For modifications and write operations to the dictionary, ConcurrentDictionary<TKey,TValue> uses fine-grained locking to ensure thread safety. (Read operations on the dictionary are performed in a lock-free manner.) However, the valueFactory
delegate is called outside the locks to avoid the problems that can arise from executing unknown code under a lock. Therefore, GetOrAdd is not atomic with regards to all other operations on the ConcurrentDictionary<TKey,TValue> class.
Since a key/value can be inserted by another thread while valueFactory
is generating a value, you cannot trust that just because valueFactory
executed, its produced value will be inserted into the dictionary and returned. If you call GetOrAdd simultaneously on different threads, valueFactory
may be called multiple times, but only one key/value pair will be added to the dictionary.
The return value depends on the presence of the key in the dictionary and whether a key/value is inserted by another thread after GetOrAdd is called but before valueFactory
generates a value:
Scenario | Return value |
---|---|
The key is already in the dictionary. | The existing value is returned. |
The key is not in the dictionary. valueFactory generates a value. On rechecking for the key, no key is found. |
The key/value is inserted into the dictionary, and the value is returned. |
The key is not in the dictionary. valueFactory generates a value. While valueFactory is generating the value, a different thread inserts a value for the key. After valueFactory executes and upon rechecking for the key, the key inserted by the other thread is found. |
The value inserted by the other thread is returned. |