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<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 または valueFactorynull

ディクショナリに含まれる要素が多すぎます。

注釈

ディクショナリに対する変更および書き込み操作の場合、 ConcurrentDictionary<TKey,TValue> は細かいロックを使用してスレッド の安全性を確保します。 (ディクショナリに対する読み取り操作は、ロックフリーの方法で実行されます)。ただし、ロックの下で不明なコードを実行することによって発生する可能性のある問題を回避するために、 valueFactory デリゲートはロックの外部で呼び出されます。 したがって、 GetOrAdd は、 ConcurrentDictionary<TKey,TValue> クラスに対する他のすべての操作に関してアトミックではありません。

valueFactoryが値を生成している間にキー/値を別のスレッドによって挿入できるため、valueFactory実行された理由だけで、生成された値がディクショナリに挿入されて返されることを信頼することはできません。 異なるスレッドで GetOrAdd を同時に呼び出す場合、 valueFactory は複数回呼び出すことができますが、ディクショナリに追加されるキーと値のペアは 1 つだけです。

戻り値は、ディクショナリ内のキーの存在と、 GetOrAdd が呼び出された後、 valueFactory が値を生成する前に別のスレッドによってキー/値が挿入されるかどうかによって異なります。

シナリオ 戻り値
キーは既にディクショナリにあります。 既存の値が返されます。
キーがディクショナリに含まれていません。 valueFactory は値を生成します。 キーの再確認時に、キーが見つかりません。 キー/値がディクショナリに挿入され、値が返されます。
キーがディクショナリに含まれていません。 valueFactory は値を生成します。 valueFactoryが値を生成している間、別のスレッドによってキーの値が挿入されます。 valueFactory実行され、キーの再確認時に、他のスレッドによって挿入されたキーが見つかります。 他のスレッドによって挿入された値が返されます。

こちらもご覧ください

適用対象

GetOrAdd(TKey, TValue)

キーがまだ存在しない場合は、キーと値のペアを 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)

指定した関数を使用して 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 参照です (Visual Basicでは Nothing)。

ディクショナリに含まれる要素が多すぎます。

注釈

ディクショナリに対する変更および書き込み操作の場合、 ConcurrentDictionary<TKey,TValue> は細かいロックを使用してスレッド の安全性を確保します。 (ディクショナリに対する読み取り操作は、ロックフリーの方法で実行されます)。ただし、ロックの下で不明なコードを実行することによって発生する可能性のある問題を回避するために、 valueFactory デリゲートはロックの外部で呼び出されます。 したがって、 GetOrAdd は、 ConcurrentDictionary<TKey,TValue> クラスに対する他のすべての操作に関してアトミックではありません。

valueFactoryが値を生成している間にキー/値を別のスレッドによって挿入できるため、valueFactory実行された理由だけで、生成された値がディクショナリに挿入されて返されることを信頼することはできません。 異なるスレッドで GetOrAdd を同時に呼び出す場合、 valueFactory は複数回呼び出すことができますが、ディクショナリに追加されるキーと値のペアは 1 つだけです。

戻り値は、ディクショナリ内のキーの存在と、 GetOrAdd が呼び出された後、 valueFactory が値を生成する前に別のスレッドによってキー/値が挿入されるかどうかによって異なります。

シナリオ 戻り値
キーは既にディクショナリにあります。 既存の値が返されます。
キーがディクショナリに含まれていません。 valueFactory は値を生成します。 キーの再確認時に、キーが見つかりません。 キー/値がディクショナリに挿入され、値が返されます。
キーがディクショナリに含まれていません。 valueFactory は値を生成します。 valueFactoryが値を生成している間、別のスレッドによってキーの値が挿入されます。 valueFactory実行され、キーの再確認時に、他のスレッドによって挿入されたキーが見つかります。 他のスレッドによって挿入された値が返されます。

適用対象