ConcurrentDictionary<TKey,TValue>.GetOrAdd 方法

定义

如果指定的键尚不存在,则将键/值对添加到 ConcurrentDictionary<TKey,TValue> 中。 如果该键已存在,则返回新值或现有值。

重载

GetOrAdd(TKey, Func<TKey,TValue>)

如果该键不存在,则通过使用指定的函数将键/值对添加到 ConcurrentDictionary<TKey,TValue> 中。 如果该键存在,则返回新值或现有值。

GetOrAdd(TKey, TValue)

如果指定的键尚不存在,则将键/值对添加到 ConcurrentDictionary<TKey,TValue> 中。 如果该键存在,则返回新值或现有值。

GetOrAdd<TArg>(TKey, Func<TKey,TArg,TValue>, TArg)

使用指定函数和参数将键/值对添加到 ConcurrentDictionary<TKey,TValue>中(若尚无键);或返回现有值(若已有键)。

示例

以下示例演示如何调用 GetOrAdd 方法:

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

如果该键不存在,则通过使用指定的函数将键/值对添加到 ConcurrentDictionary<TKey,TValue> 中。 如果该键存在,则返回新值或现有值。

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

参数

key
TKey

要添加的元素的键。

valueFactory
Func<TKey,TValue>

用于为键生成值的函数。

返回

TValue

键的值。 如果字典中已存在该键,则为该键的现有值;如果字典中不存在该键,则为新值。

例外

keyvalueFactorynull

字典包含过多元素。

注解

对于对字典的修改和写入操作, ConcurrentDictionary<TKey,TValue> 请使用精细锁定来确保线程安全。 (字典上的读取操作以无锁方式执行。) 但是, valueFactory 在锁外部调用委托,以避免在锁下执行未知代码时可能出现的问题。 因此, GetOrAdd 对于 类上的所有其他操作,不是原子的 ConcurrentDictionary<TKey,TValue>

由于键/值可以在生成值时 valueFactory 由另一个线程插入,因此不能仅因为 valueFactory 执行,它生成的值将插入字典并返回。 如果同时在不同的线程上调用 GetOrAddvalueFactory 可能会多次调用,但只会将一个键/值对添加到字典中。

返回值取决于字典中是否存在键,以及键/值是否由另一个线程在调用 后 GetOrAdd 插入,然后 valueFactory 生成值:

方案 返回值
该键已在字典中。 返回现有值。
键不在字典中。 valueFactory 生成值。 重新检查密钥时,找不到任何密钥。 键/值将插入字典中,并返回值。
键不在字典中。 valueFactory 生成值。 生成值时 valueFactory ,另一个线程会为键插入值。 执行并重新检查密钥后 valueFactory ,会找到另一个线程插入的键。 返回由另一个线程插入的值。

另请参阅

适用于

GetOrAdd(TKey, TValue)

Source:
ConcurrentDictionary.cs
Source:
ConcurrentDictionary.cs
Source:
ConcurrentDictionary.cs

如果指定的键尚不存在,则将键/值对添加到 ConcurrentDictionary<TKey,TValue> 中。 如果该键存在,则返回新值或现有值。

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

参数

key
TKey

要添加的元素的键。

value
TValue

当键不存在时要添加的值。

返回

TValue

键的值。 如果字典中已存在该键,则为该键的现有值;如果字典中不存在该键,则为新值。

例外

keynull

字典包含过多元素。

另请参阅

适用于

GetOrAdd<TArg>(TKey, Func<TKey,TArg,TValue>, TArg)

Source:
ConcurrentDictionary.cs
Source:
ConcurrentDictionary.cs
Source:
ConcurrentDictionary.cs

使用指定函数和参数将键/值对添加到 ConcurrentDictionary<TKey,TValue>中(若尚无键);或返回现有值(若已有键)。

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

类型参数

TArg

要传递到 valueFactory的参数的类型。

参数

key
TKey

要添加的元素的键。

valueFactory
Func<TKey,TArg,TValue>

用于为键生成值的函数。

factoryArgument
TArg

要传入 valueFactory 的参数值。

返回

TValue

键的值。 如果字典中已存在该键,则为该键的现有值;如果字典中不存在该键,则为新值。

例外

keynull 引用(在 Visual Basic 中为 Nothing)。

字典包含过多元素。

注解

对于对字典的修改和写入操作, ConcurrentDictionary<TKey,TValue> 请使用精细锁定来确保线程安全。 (字典上的读取操作以无锁方式执行。) 但是, valueFactory 在锁外部调用委托,以避免在锁下执行未知代码时可能出现的问题。 因此, GetOrAdd 对于 类上的所有其他操作,不是原子的 ConcurrentDictionary<TKey,TValue>

由于键/值可以在生成值时 valueFactory 由另一个线程插入,因此不能仅因为 valueFactory 执行,它生成的值将插入字典并返回。 如果同时在不同的线程上调用 GetOrAddvalueFactory 可能会多次调用,但只会将一个键/值对添加到字典中。

返回值取决于字典中是否存在键,以及键/值是否由另一个线程在调用 后 GetOrAdd 插入,然后 valueFactory 生成值:

方案 返回值
该键已在字典中。 返回现有值。
键不在字典中。 valueFactory 生成值。 重新检查密钥时,找不到任何密钥。 键/值将插入字典中,并返回值。
键不在字典中。 valueFactory 生成值。 生成值时 valueFactory ,另一个线程会为键插入值。 执行并重新检查密钥后 valueFactory ,会找到另一个线程插入的键。 返回由另一个线程插入的值。

适用于