web-dev-qa-db-ja.com

keyValuePairをディクショナリに直接追加することはできません

_KeyValuePair<T,U>_を_Dictionary<T, U>_に追加したかったのですが、できませんでした。キーと値を別々に渡す必要があります。つまり、Addメソッドは、挿入する新しいKeyValuePairオブジェクトを作成する必要があるため、非常に効率的ではありません。 AddメソッドにAdd(KeyValuePair<T, U>)オーバーロードがないとは思えません。誰もがこの明らかな見落としの考えられる理由を提案できますか?

30
Dave

1分バックアップしてください...見落としの前に、新しいKeyValuePairの作成が本当に非効率的かどうかを確認する必要があります。

まず、Dictionaryクラスは、キーと値のペアのセットとして内部的に実装されているのではなく、一連の配列として実装されています。それはさておき、それが単なるKeyValuePairのセットであると仮定して、効率を見てみましょう。

最初に気づくのは KeyValuePair が構造であることです。これが実際に意味することは、メソッドパラメータとして渡されるには、スタックからヒープにコピーされる必要があるということです。 KeyValuePairがディクショナリに追加されると、値タイプのセマンティクスを保証するために、もう一度コピーする必要があります。

KeyとValueをパラメーターとして渡すために、各パラメーターは値タイプまたは参照タイプのいずれかになります。それらが値タイプの場合、パフォーマンスはKeyValuePairルートと非常に似たものになります。それらが参照型の場合、アドレスを渡すだけでコピーはほとんど必要ないので、これは実際にはより高速な実装になります。最良の場合と最悪の場合の両方で、KeyValuePair構造体自体のオーバーヘッドが増加するため、このオプションはKeyValuePairオプションよりもわずかに優れています。

32
Tim Copenhaver

Add(KeyValuePair<TKey,TValue>)メソッドを提供するIDictionary<TKey,TValue>インターフェースを使用できます。

IDictionary<int, string> dictionary = new Dictionary<int, string>();
dictionary.Add(new KeyValuePair<int,string>(0,"0"));
dictionary.Add(new KeyValuePair<int,string>(1,"1"));
32
DmitryG

そのようなメソッド– ICollection<KeyValuePair<K, T>>.Addがありますが、explicitly実装されているため、それにアクセスするには、ディクショナリオブジェクトをそのインターフェイスにキャストする必要があります。

((ICollection<KeyValuePair<KeyType, ValueType>>)myDict).Add(myPair);

見る

このメソッドの page には例が含まれています。

14
Richard

誤解しない限り、.NET 4.5および4.6では、辞書にKeyValuePairを追加する機能が追加されています。 (私が間違っている場合は、通知してください。この回答は削除します。)

https://msdn.Microsoft.com/en-us/library/cc673027%28v=vs.110%29.aspx

上記のリンクから、関連する情報は次のコード例です。

public static void Main() 
{
    // Create a new dictionary of strings, with string keys, and 
    // access it through the generic ICollection interface. The 
    // generic ICollection interface views the dictionary as a 
    // collection of KeyValuePair objects with the same type 
    // arguments as the dictionary. 
    //
    ICollection<KeyValuePair<String, String>> openWith =
        new Dictionary<String, String>();

    // Add some elements to the dictionary. When elements are  
    // added through the ICollection<T> interface, the keys 
    // and values must be wrapped in KeyValuePair objects. 
    //
    openWith.Add(new KeyValuePair<String,String>("txt", "notepad.exe"));
    openWith.Add(new KeyValuePair<String,String>("bmp", "Paint.exe"));
    openWith.Add(new KeyValuePair<String,String>("dib", "Paint.exe"));
    openWith.Add(new KeyValuePair<String,String>("rtf", "wordpad.exe"));

    ...
}

ご覧のとおり、Dictionaryタイプの新しいオブジェクトが作成され、openWithと呼ばれます。次に、新しいKVPオブジェクトが作成され、.Addメソッドを使用してopenWithに追加されます。

2
Machtyn

誰かが本当にこれをしたいのであれば、ここに拡張機能があります

    public static void Add<T, U>(this IDictionary<T, U> dic, KeyValuePair<T, U> KVP)
    {
        dic.Add(KVP.Key, KVP.Value);
    }

ただし、実際にこれを行う必要がない場合は、これを行わないことをお勧めします

2
WiiMaxx

dictionaryクラスの列挙子がKeyValuePairを返すからといって、それが内部的にどのように実装されるかを意味するものではありません。

kVPに合格する必要がある場合は、IDictionaryを使用してください。これは、その形式ですでに取得されているためです。それ以外の場合は、割り当てを使用するか、Addメソッドを使用します。

1
Mike Corcoran

それを拡張機能としてプロジェクトに追加するだけでは何が悪いのでしょうか?

namespace System.Collection.Generic
{
    public static class DictionaryExtensions
    {
        public static void AddKeyValuePair<K,V>(this IDictionary<K, V> me, KeyValuePair<K, V> other)
        {
            me.Add(other.Key, other.Value);
        }
    }
}
0
Machtyn