web-dev-qa-db-ja.com

辞書に新しい項目を追加または既存の項目を更新する方法

いくつかのレガシコードでは、キーが既に存在する場合、新しいキーと値のアイテムの追加または値の更新を容易にするために、次の拡張メソッドを参照しています。

方法1(レガシーコード)。

public static void CreateNewOrUpdateExisting<TKey, TValue>(
    this IDictionary<TKey, TValue> map, TKey key, TValue value)
{            
    if (map.ContainsKey(key))
    {
        map[key] = value;
    }
    else
    {
        map.Add(key, value);
    }
}

ただし、map[key]=valueがまったく同じ仕事をすることを確認しました。つまり、このメソッドは、以下のメソッド2に置き換えることができます。

方法-2。

public static void CreateNewOrUpdateExisting<TKey, TValue>(
    this IDictionary<TKey, TValue> map, TKey key, TValue value)
{
    map[key] = value;
}

さて、私の質問は.. Method-1をMethod-2に置き換えた場合、何か問題がありますか?どんなシナリオでも壊れますか?

また、これはHashTableとDictionaryの違いだったと思います。 HashTableでは、ディクショナリではできませんが、インデクサーを使用してアイテムを更新したり、新しいアイテムを追加したりできます。この違いは、C#> 3.0バージョンで解消されましたか?

このメソッドの目的は、ユーザーが同じKey-Valueを再度送信した場合に例外をスローしすぎないことです。メソッドは、新しい値でエントリを更新し、新しいKey-Valueペアがメソッドに送信された場合に新しいエントリを作成する必要があります。

186

Method-1をMethod-2に置き換えた場合、問題はありますか?

いいえ、map[key] = valueを使用してください。 2つのオプションは同等です。


Dictionary<>Hashtableについて:Reflectorを起動すると、両方のクラスのインデクサーセッターがthis.Insert(key, value, add: false);を呼び出し、addパラメーターが重複キーを挿入するときに例外をスローすることがわかります。したがって、動作は両方のクラスで同じです。

196
ulrichb

大丈夫。開発者は通常map[key] = valueの意味を知っているので、ソースからCreateNewOrUpdateExistingを削除して、コードでmap[key] = valueを直接使用します。

37
Steven

古い質問ですが、質問が書かれた時点で.net 4.0がすでに起動しているため、さらに以下を追加する必要があります。

.net 4.0以降では、スレッドセーフなコレクションを含む名前空間System.Collections.Concurrentがあります。

コレクションSystem.Collections.Concurrent.ConcurrentDictionary<>は、まさにあなたが望むことをします。 AddOrUpdate()メソッドがあり、スレッドセーフであるという利点があります。

高性能のシナリオで複数のスレッドを処理していない場合は、すでに指定されているmap[key] = valueの回答が高速になります。

ほとんどのシナリオでは、このパフォーマンス上の利点はわずかです。もしそうなら、私はConcurrentDictionaryを使用することをお勧めします:

  1. それはフレームワークにあります-よりテストされており、あなたはコードを維持しなければならない人ではありません
  2. スケーラブルです:マルチスレッドに切り替えると、コードはすでに準備されています
17
Luis Filipe

機能的には、それらは同等です。

2つではなく1つのルックアップのみを行うため、パフォーマンス面ではmap[key] = valueの方が高速です。

スタイル的には、短いほど良い:)

ほとんどの場合、コードはマルチスレッドコンテキストで正常に動作するようです。ただし、追加の同期なしでnotスレッドセーフです。

6
ya23