ConcurrentDictionary<TKey,TValue>.AddOrUpdate 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, or updates a key/value pair in the ConcurrentDictionary<TKey,TValue> if the key already exists.
Overloads
AddOrUpdate(TKey, Func<TKey,TValue>, Func<TKey,TValue,TValue>) |
Uses the specified functions to add a key/value pair to the ConcurrentDictionary<TKey,TValue> if the key does not already exist, or to update a key/value pair in the ConcurrentDictionary<TKey,TValue> if the key already exists. |
AddOrUpdate(TKey, TValue, Func<TKey,TValue,TValue>) |
Adds a key/value pair to the ConcurrentDictionary<TKey,TValue> if the key does not already exist, or updates a key/value pair in the ConcurrentDictionary<TKey,TValue> by using the specified function if the key already exists. |
AddOrUpdate<TArg>(TKey, Func<TKey,TArg,TValue>, Func<TKey,TValue,TArg,TValue>, TArg) |
Uses the specified functions and argument to add a key/value pair to the ConcurrentDictionary<TKey,TValue> if the key does not already exist, or to update a key/value pair in the ConcurrentDictionary<TKey,TValue> if the key already exists. |
Examples
The following example shows how to call the AddOrUpdate 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
AddOrUpdate(TKey, Func<TKey,TValue>, Func<TKey,TValue,TValue>)
- Source:
- ConcurrentDictionary.cs
- Source:
- ConcurrentDictionary.cs
- Source:
- ConcurrentDictionary.cs
Uses the specified functions to add a key/value pair to the ConcurrentDictionary<TKey,TValue> if the key does not already exist, or to update a key/value pair in the ConcurrentDictionary<TKey,TValue> if the key already exists.
public:
TValue AddOrUpdate(TKey key, Func<TKey, TValue> ^ addValueFactory, Func<TKey, TValue, TValue> ^ updateValueFactory);
public TValue AddOrUpdate (TKey key, Func<TKey,TValue> addValueFactory, Func<TKey,TValue,TValue> updateValueFactory);
member this.AddOrUpdate : 'Key * Func<'Key, 'Value> * Func<'Key, 'Value, 'Value> -> 'Value
Public Function AddOrUpdate (key As TKey, addValueFactory As Func(Of TKey, TValue), updateValueFactory As Func(Of TKey, TValue, TValue)) As TValue
Parameters
- key
- TKey
The key to be added or whose value should be updated.
- addValueFactory
- Func<TKey,TValue>
The function used to generate a value for an absent key.
- updateValueFactory
- Func<TKey,TValue,TValue>
The function used to generate a new value for an existing key based on the key's existing value.
Returns
The new value for the key. This will be either be the result of addValueFactory
(if the key was absent) or the result of updateValueFactory
(if the key was present).
Exceptions
key
, addValueFactory
, or updateValueFactory
is null
.
The dictionary contains too many elements.
Remarks
If you call AddOrUpdate simultaneously on different threads, addValueFactory
may be called multiple times, but its key/value pair might not be added to the dictionary for every call.
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). The addValueFactory
and updateValueFactory
delegates may be executed multiple times to verify the value was added or updated as expected. However, they are called outside the locks to avoid the problems that can arise from executing unknown code under a lock. Therefore, AddOrUpdate is not atomic with regards to all other operations on the ConcurrentDictionary<TKey,TValue> class.
See also
Applies to
AddOrUpdate(TKey, TValue, Func<TKey,TValue,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, or updates a key/value pair in the ConcurrentDictionary<TKey,TValue> by using the specified function if the key already exists.
public:
TValue AddOrUpdate(TKey key, TValue addValue, Func<TKey, TValue, TValue> ^ updateValueFactory);
public TValue AddOrUpdate (TKey key, TValue addValue, Func<TKey,TValue,TValue> updateValueFactory);
member this.AddOrUpdate : 'Key * 'Value * Func<'Key, 'Value, 'Value> -> 'Value
Public Function AddOrUpdate (key As TKey, addValue As TValue, updateValueFactory As Func(Of TKey, TValue, TValue)) As TValue
Parameters
- key
- TKey
The key to be added or whose value should be updated.
- addValue
- TValue
The value to be added for an absent key.
- updateValueFactory
- Func<TKey,TValue,TValue>
The function used to generate a new value for an existing key based on the key's existing value.
Returns
The new value for the key. This will be either be addValue
(if the key was absent) or the result of updateValueFactory
(if the key was present).
Exceptions
key
or updateValueFactory
is null
.
The dictionary contains too many elements.
Examples
The following code example shows how to initialize an ConcurrentDictionary<TKey,TValue> and how to use the AddOrUpdate method to add an additional item to the collection, and update the existing items.
using System;
using System.Collections.Concurrent;
class CD_Ctor
{
// Demonstrates:
// ConcurrentDictionary<TKey, TValue> ctor(concurrencyLevel, initialCapacity)
// ConcurrentDictionary<TKey, TValue>[TKey]
static void Main()
{
// We know how many items we want to insert into the ConcurrentDictionary.
// So set the initial capacity to some prime number above that, to ensure that
// the ConcurrentDictionary does not need to be resized while initializing it.
int HIGHNUMBER = 64;
int initialCapacity = 101;
// The higher the concurrencyLevel, the higher the theoretical number of operations
// that could be performed concurrently on the ConcurrentDictionary. However, global
// operations like resizing the dictionary take longer as the concurrencyLevel rises.
// For the purposes of this example, we'll compromise at numCores * 2.
int numProcs = Environment.ProcessorCount;
int concurrencyLevel = numProcs * 2;
// Construct the dictionary with the desired concurrencyLevel and initialCapacity
ConcurrentDictionary<int, int> cd = new ConcurrentDictionary<int, int>(concurrencyLevel, initialCapacity);
// Initialize the dictionary
for (int i = 1; i <= HIGHNUMBER; i++) cd[i] = i * i;
Console.WriteLine("The square of 23 is {0} (should be {1})", cd[23], 23 * 23);
// Now iterate through, adding one to the end of the list. Existing items should be updated to be divided by their
// key and a new item will be added that is the square of its key.
for (int i = 1; i <= HIGHNUMBER + 1; i++)
cd.AddOrUpdate(i, i * i, (k,v) => v / i);
Console.WriteLine("The square root of 529 is {0} (should be {1})", cd[23], 529 / 23);
Console.WriteLine("The square of 65 is {0} (should be {1})", cd[HIGHNUMBER + 1], ((HIGHNUMBER + 1) * (HIGHNUMBER + 1)));
}
}
open System
open System.Collections.Concurrent
// Demonstrates:
// ConcurrentDictionary<TKey, TValue> ctor(concurrencyLevel, initialCapacity)
// ConcurrentDictionary<TKey, TValue>[TKey]
// We know how many items we want to insert into the ConcurrentDictionary.
// So set the initial capacity to some prime number above that, to ensure that
// the ConcurrentDictionary does not need to be resized while initializing it.
let HIGHNUMBER = 64
let initialCapacity = 101
// The higher the concurrencyLevel, the higher the theoretical number of operations
// that could be performed concurrently on the ConcurrentDictionary. However, global
// operations like resizing the dictionary take longer as the concurrencyLevel rises.
// For the purposes of this example, we'll compromise at numCores * 2.
let numProcs = Environment.ProcessorCount
let concurrencyLevel = numProcs * 2
// Construct the dictionary with the desired concurrencyLevel and initialCapacity
let cd = ConcurrentDictionary<int, int>(concurrencyLevel, initialCapacity)
// Initialize the dictionary
for i = 1 to HIGHNUMBER do
cd[i] <- i * i
printfn $"The square of 23 is {cd[23]} (should be {23 * 23})"
// Now iterate through, adding one to the end of the list. Existing items should be updated to be divided by their
// key and a new item will be added that is the square of its key.
for i = 1 to HIGHNUMBER + 1 do
cd.AddOrUpdate(i, i * i, (fun k v -> v / i)) |> ignore
printfn $"The square root of 529 is {cd[23]} (should be {529 / 23})"
printfn $"The square of 65 is {cd[HIGHNUMBER + 1]} (should be {(HIGHNUMBER + 1) * (HIGHNUMBER + 1)})"
Imports System.Collections.Concurrent
Class CD_Ctor
' Demonstrates:
' ConcurrentDictionary<TKey, TValue> ctor(concurrencyLevel, initialCapacity)
' ConcurrentDictionary<TKey, TValue>[TKey]
Public Shared Sub Main()
' We know how many items we want to insert into the ConcurrentDictionary.
' So set the initial capacity to some prime number above that, to ensure that
' the ConcurrentDictionary does not need to be resized while initializing it.
Dim HIGHNUMBER As Integer = 64
Dim initialCapacity As Integer = 101
' The higher the concurrencyLevel, the higher the theoretical number of operations
' that could be performed concurrently on the ConcurrentDictionary. However, global
' operations like resizing the dictionary take longer as the concurrencyLevel rises.
' For the purposes of this example, we'll compromise at numCores * 2.
Dim numProcs As Integer = Environment.ProcessorCount
Dim concurrencyLevel As Integer = numProcs * 2
' Construct the dictionary with the desired concurrencyLevel and initialCapacity
Dim cd As New ConcurrentDictionary(Of Integer, Integer)(concurrencyLevel, initialCapacity)
' Initialize the dictionary
For i As Integer = 1 To HIGHNUMBER
cd(i) = i * i
Next
Console.WriteLine("The square of 23 is {0} (should be {1})", cd(23), 23 * 23)
' Now iterate through, adding one to the end of the list. Existing items should be updated to be divided by their
' key and a new item will be added that is the square of its key.
For i As Integer = 1 To HIGHNUMBER + 1
cd.AddOrUpdate(i, i * i, Function(k, v)
Return v / i
End Function)
Next
Console.WriteLine("The square root of 529 is {0} (should be {1})", cd(23), 529 / 23)
Console.WriteLine("The square of 65 is {0} (should be {1})", cd(HIGHNUMBER + 1), ((HIGHNUMBER + 1) * (HIGHNUMBER + 1)))
End Sub
End Class
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.) The addValueFactory
and updateValueFactory
delegates may be executed multiple times to verify the value was added or updated as expected. However, they are called outside the locks to avoid the problems that can arise from executing unknown code under a lock. Therefore, AddOrUpdate is not atomic with regards to all other operations on the ConcurrentDictionary<TKey,TValue> class.
See also
Applies to
AddOrUpdate<TArg>(TKey, Func<TKey,TArg,TValue>, Func<TKey,TValue,TArg,TValue>, TArg)
- Source:
- ConcurrentDictionary.cs
- Source:
- ConcurrentDictionary.cs
- Source:
- ConcurrentDictionary.cs
Uses the specified functions and argument to add a key/value pair to the ConcurrentDictionary<TKey,TValue> if the key does not already exist, or to update a key/value pair in the ConcurrentDictionary<TKey,TValue> if the key already exists.
public:
generic <typename TArg>
TValue AddOrUpdate(TKey key, Func<TKey, TArg, TValue> ^ addValueFactory, Func<TKey, TValue, TArg, TValue> ^ updateValueFactory, TArg factoryArgument);
public TValue AddOrUpdate<TArg> (TKey key, Func<TKey,TArg,TValue> addValueFactory, Func<TKey,TValue,TArg,TValue> updateValueFactory, TArg factoryArgument);
member this.AddOrUpdate : 'Key * Func<'Key, 'Arg, 'Value> * Func<'Key, 'Value, 'Arg, 'Value> * 'Arg -> 'Value
Public Function AddOrUpdate(Of TArg) (key As TKey, addValueFactory As Func(Of TKey, TArg, TValue), updateValueFactory As Func(Of TKey, TValue, TArg, TValue), factoryArgument As TArg) As TValue
Type Parameters
- TArg
The type of an argument to pass into addValueFactory
and updateValueFactory
.
Parameters
- key
- TKey
The key to be added or whose value should be updated.
- addValueFactory
- Func<TKey,TArg,TValue>
The function used to generate a value for an absent key.
- updateValueFactory
- Func<TKey,TValue,TArg,TValue>
The function used to generate a new value for an existing key based on the key's existing value.
- factoryArgument
- TArg
An argument to pass into addValueFactory
and updateValueFactory
.
Returns
The new value for the key. This will be either be the result of addValueFactory
(if the key was absent) or the result of updateValueFactory
(if the key was present).
Exceptions
key
, addValueFactory
, or updateValueFactory
is a null reference (Nothing in Visual Basic).
The dictionary contains too many elements.
Remarks
If you call AddOrUpdate simultaneously on different threads, addValueFactory
may be called multiple times, but its key/value pair might not be added to the dictionary for every call.
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.) The addValueFactory
and updateValueFactory
delegates may be executed multiple times to verify the value was added or updated as expected. However, they are called outside the locks to avoid the problems that can arise from executing unknown code under a lock. Therefore, AddOrUpdate is not atomic with regards to all other operations on the ConcurrentDictionary<TKey,TValue> class.