web-dev-qa-db-ja.com

辞書値の取得のベストプラクティス

私は最近Dictionary.TryGetValue(TKey key, out TValue value)に気付き、どちらが辞書から値を取得するためのより良いアプローチであるかについて興味がありました。

私は伝統的にやってきました:

if (myDict.Contains(someKey))
     someVal = myDict[someKey];
     ...

知らない限りhasそこにいる。

ただ行う方が良いですか:

if (myDict.TryGetValue(somekey, out someVal)
    ...

どちらが良い方法ですか?一方が他方より速いですか? Tryバージョンは、内部でtry/catchを「飲み込み」、それをロジックとして使用するため、遅くなると思いますか?

79

FindGetValueはわずかに高速です。FindEntryは1回しか呼び出されないためです。

どれくらい速い?手元のデータセットに依存します。 Containsメソッドを呼び出すと、Dictionaryは内部検索を実行してそのインデックスを見つけます。 trueが返される場合、実際の値を取得するために別のインデックス検索が必要です。 TryGetValueを使用すると、インデックスが1回だけ検索され、見つかった場合は変数に値が割り当てられます。

参考までに、実際にはエラーをキャッチしているわけではありません。

それは呼び出しています:

public bool TryGetValue(TKey key, out TValue value)
{
    int index = this.FindEntry(key);
    if (index >= 0)
    {
        value = this.entries[index].value;
        return true;
    }
    value = default(TValue);
    return false;
}

ContainsKeyは次のとおりです。

public bool ContainsKey(TKey key)
{
    return (this.FindEntry(key) >= 0);
}
84
Micah

実際、TryGetValueは高速です。どれくらい速い?手元のデータセットに依存します。 Containsメソッドを呼び出すと、Dictionaryは内部検索を実行してそのインデックスを見つけます。 trueが返される場合、実際の値を取得するために別のインデックス検索が必要です。 TryGetValueを使用すると、インデックスが1回だけ検索され、見つかった場合は変数に値が割り当てられます。

編集:

さて、あなたの混乱を理解したので、詳しく説明します。

ケース1:

if (myDict.Contains(someKey))
     someVal = myDict[someKey];

この場合、FindEntryには2つの呼び出しがあり、1つはキーが存在するかどうかを確認し、もう1つはキーを取得します

ケース2:

myDict.TryGetValue(somekey, out someVal)

この場合、結果のインデックスは同じメソッドで実際に取得するために保持されるため、FindKeyの呼び出しは1つだけです。

29
Diadistis

Trygetvalueは次のようなことをしていると思います。

if(myDict.ReallyOptimisedVersionofContains(someKey))
{ 
  someVal = myDict[someKey];
  return true;
}
return false;

うまくいけば、どこにもトライ/キャッチしないでください。

これは本当に便利な方法だと思います。通常は、1行または2行のコードを保存するために使用します。

1
Jennifer