ConcurrentDictionary<TKey,TValue>.GetOrAdd Método

Definição

Adiciona um par chave/valor ao ConcurrentDictionary<TKey,TValue> caso a chave ainda não exista. Devolve o novo valor, ou o valor existente se a chave já existir.

Sobrecargas

Name Description
GetOrAdd(TKey, Func<TKey,TValue>)

Adiciona um par chave/valor ao ConcurrentDictionary<TKey,TValue> usar a função especificada, caso a chave ainda não exista. Devolve o novo valor, ou o valor existente se a chave existir.

GetOrAdd(TKey, TValue)

Adiciona um par chave/valor ao ConcurrentDictionary<TKey,TValue> caso a chave ainda não exista. Devolve o novo valor, ou o valor existente se a chave existir.

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

Adiciona um par chave/valor ao ConcurrentDictionary<TKey,TValue> usando a função especificada e um argumento se a chave ainda não existir, ou devolve o valor existente se a chave existir.

Exemplos

O exemplo seguinte mostra como chamar o GetOrAdd método:

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

Adiciona um par chave/valor ao ConcurrentDictionary<TKey,TValue> usar a função especificada, caso a chave ainda não exista. Devolve o novo valor, ou o valor existente se a chave existir.

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

Parâmetros

key
TKey

A chave do elemento a adicionar.

valueFactory
Func<TKey,TValue>

A função usada para gerar um valor para a chave.

Devoluções

TValue

O valor da chave. Este será ou o valor existente da chave se a chave já estiver no dicionário, ou o novo valor se a chave não estiver no dicionário.

Exceções

key ou valueFactory é null.

O dicionário contém demasiados elementos.

Observações

Para modificações e operações de escrita no dicionário, ConcurrentDictionary<TKey,TValue> utiliza bloqueio de granulação fina para garantir a segurança das threads. (As operações de leitura no dicionário são realizadas de forma sem bloqueios.) No entanto, o valueFactory delegado é chamado para fora dos bloqueios para evitar os problemas que podem surgir ao executar código desconhecido sob um bloqueio. Portanto, GetOrAdd não é atómico relativamente a todas as outras operações na ConcurrentDictionary<TKey,TValue> classe.

Como uma chave/valor pode ser inserida por outro thread enquanto valueFactory está a gerar um valor, não se pode confiar que, só porque valueFactory executado, o seu valor produzido será inserido no dicionário e devolvido. Se chamar GetOrAdd simultaneamente em diferentes threads, valueFactory pode ser chamado várias vezes, mas apenas um par chave/valor será adicionado ao dicionário.

O valor de retorno depende da presença da chave no dicionário e se uma chave/valor é inserida por outro thread depois GetOrAdd de ser chamada mas antes valueFactory gerar um valor:

Scenario Valor de retorno
A chave já está no dicionário. O valor existente é devolvido.
A chave não está no dicionário. valueFactory gera um valor. Ao verificar novamente a chave, não é encontrada nenhuma chave. A chave/valor é inserida no dicionário e o valor é devolvido.
A chave não está no dicionário. valueFactory gera um valor. Enquanto valueFactory está a gerar o valor, uma thread diferente insere um valor para a chave. Após valueFactory a execução e ao verificar novamente a chave, a chave inserida pelo outro thread é encontrada. O valor inserido pela outra thread é devolvido.

Ver também

Aplica-se a

GetOrAdd(TKey, TValue)

Adiciona um par chave/valor ao ConcurrentDictionary<TKey,TValue> caso a chave ainda não exista. Devolve o novo valor, ou o valor existente se a chave existir.

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

Parâmetros

key
TKey

A chave do elemento a adicionar.

value
TValue

O valor a acrescentar, se a chave ainda não existir.

Devoluções

TValue

O valor da chave. Este será ou o valor existente da chave se a chave já estiver no dicionário, ou o novo valor se a chave não estiver no dicionário.

Exceções

key é null.

O dicionário contém demasiados elementos.

Ver também

Aplica-se a

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

Adiciona um par chave/valor ao ConcurrentDictionary<TKey,TValue> usando a função especificada e um argumento se a chave ainda não existir, ou devolve o valor existente se a chave existir.

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

Parâmetros de Tipo Genérico

TArg

O tipo de argumento a passar para valueFactory.

Parâmetros

key
TKey

A chave do elemento a adicionar.

valueFactory
Func<TKey,TArg,TValue>

A função usada para gerar um valor para a chave.

factoryArgument
TArg

Um valor de argumento a passar para valueFactory.

Devoluções

TValue

O valor da chave. Este será ou o valor existente da chave se a chave já estiver no dicionário, ou o novo valor se a chave não estiver no dicionário.

Exceções

key é uma referência null (Nada em Visual Basic).

O dicionário contém demasiados elementos.

Observações

Para modificações e operações de escrita no dicionário, ConcurrentDictionary<TKey,TValue> utiliza bloqueio de granulação fina para garantir a segurança das threads. (As operações de leitura no dicionário são realizadas de forma sem bloqueios.) No entanto, o valueFactory delegado é chamado para fora dos bloqueios para evitar os problemas que podem surgir ao executar código desconhecido sob um bloqueio. Portanto, GetOrAdd não é atómico relativamente a todas as outras operações na ConcurrentDictionary<TKey,TValue> classe.

Como uma chave/valor pode ser inserida por outro thread enquanto valueFactory está a gerar um valor, não se pode confiar que, só porque valueFactory executado, o seu valor produzido será inserido no dicionário e devolvido. Se chamar GetOrAdd simultaneamente em diferentes threads, valueFactory pode ser chamado várias vezes, mas apenas um par chave/valor será adicionado ao dicionário.

O valor de retorno depende da presença da chave no dicionário e se uma chave/valor é inserida por outro thread depois GetOrAdd de ser chamada mas antes valueFactory gerar um valor:

Scenario Valor de retorno
A chave já está no dicionário. O valor existente é devolvido.
A chave não está no dicionário. valueFactory gera um valor. Ao verificar novamente a chave, não é encontrada nenhuma chave. A chave/valor é inserida no dicionário e o valor é devolvido.
A chave não está no dicionário. valueFactory gera um valor. Enquanto valueFactory está a gerar o valor, uma thread diferente insere um valor para a chave. Após valueFactory a execução e ao verificar novamente a chave, a chave inserida pelo outro thread é encontrada. O valor inserido pela outra thread é devolvido.

Aplica-se a