Поделиться через


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>)

Исходный код:
ConcurrentDictionary.cs
Исходный код:
ConcurrentDictionary.cs
Исходный код:
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

Значение для ключа. Этим значением будет существующее значение ключа, если ключ уже имеется в словаре, или новое значение, если ключ не существовал в словаре.

Исключения

Параметр key или valueFactory имеет значение null.

Словарь содержит слишком много элементов.

Комментарии

Для операций изменения и записи в словарь использует детализированную блокировку для ConcurrentDictionary<TKey,TValue> обеспечения потокобезопасности. (Операции чтения в словаре выполняются без блокировки.) Однако делегат вызывается вне блокировок, valueFactory чтобы избежать проблем, которые могут возникнуть при выполнении неизвестного кода под блокировкой. Таким образом, GetOrAdd не является атомарным по отношению ко всем остальным операциям в ConcurrentDictionary<TKey,TValue> классе .

Так как ключ/значение может быть вставлен другим потоком во время valueFactory создания значения, вы не можете доверять ему только потому, что valueFactory выполнено, созданное значение будет вставлено в словарь и возвращено. При одновременном вызове GetOrAdd в разных потоках valueFactory может вызываться несколько раз, но в словарь будет добавлена только одна пара "ключ-значение".

Возвращаемое значение зависит от наличия ключа в словаре и от того, вставляется ли ключ или значение другим потоком после GetOrAdd вызова , но до valueFactory создания значения:

Сценарий Возвращаемое значение
Ключ уже находится в словаре. Возвращается существующее значение.
Ключ отсутствует в словаре. valueFactory создает значение . При повторной проверки ключа ключ не найден. Ключ/значение вставляется в словарь и возвращается значение.
Ключ отсутствует в словаре. valueFactory создает значение . При valueFactory создании значения другой поток вставляет значение для ключа. После valueFactory выполнения и повторной проверки ключа обнаруживается ключ, вставленный другим потоком. Возвращается значение, вставленное другим потоком.

См. также раздел

Применяется к

GetOrAdd(TKey, TValue)

Исходный код:
ConcurrentDictionary.cs
Исходный код:
ConcurrentDictionary.cs
Исходный код:
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

Значение для ключа. Этим значением будет существующее значение ключа, если ключ уже имеется в словаре, или новое значение, если ключ не существовал в словаре.

Исключения

key имеет значение null.

Словарь содержит слишком много элементов.

См. также раздел

Применяется к

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

Исходный код:
ConcurrentDictionary.cs
Исходный код:
ConcurrentDictionary.cs
Исходный код:
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

Значение для ключа. Этим значением будет существующее значение ключа, если ключ уже имеется в словаре, или новое значение, если ключ не существовал в словаре.

Исключения

key является ссылкой null (Nothing в Visual Basic).

Словарь содержит слишком много элементов.

Комментарии

Для операций изменения и записи в словарь использует детализированную блокировку для ConcurrentDictionary<TKey,TValue> обеспечения потокобезопасности. (Операции чтения в словаре выполняются без блокировки.) Однако делегат вызывается вне блокировок, valueFactory чтобы избежать проблем, которые могут возникнуть при выполнении неизвестного кода под блокировкой. Таким образом, GetOrAdd не является атомарным по отношению ко всем остальным операциям в ConcurrentDictionary<TKey,TValue> классе .

Так как ключ/значение может быть вставлен другим потоком во время valueFactory создания значения, вы не можете доверять ему только потому, что valueFactory выполнено, созданное значение будет вставлено в словарь и возвращено. При одновременном вызове GetOrAdd в разных потоках valueFactory может вызываться несколько раз, но в словарь будет добавлена только одна пара "ключ-значение".

Возвращаемое значение зависит от наличия ключа в словаре и от того, вставляется ли ключ или значение другим потоком после GetOrAdd вызова , но до valueFactory создания значения:

Сценарий Возвращаемое значение
Ключ уже находится в словаре. Возвращается существующее значение.
Ключ отсутствует в словаре. valueFactory создает значение . При повторной проверки ключа ключ не найден. Ключ/значение вставляется в словарь и возвращается значение.
Ключ отсутствует в словаре. valueFactory создает значение . При valueFactory создании значения другой поток вставляет значение для ключа. После valueFactory выполнения и повторной проверки ключа обнаруживается ключ, вставленный другим потоком. Возвращается значение, вставленное другим потоком.

Применяется к