236

コードを想像してください:

public class obj
{
    // elided
}

public static Dictionary<string, obj> dict = new Dictionary<string, obj>();

方法 1

public static obj FromDict1(string name)
{
    if (dict.ContainsKey(name))
    {
        return dict[name];
    }
    return null;
}

方法 2

public static obj FromDict2(string name)
{
    try
    {
        return dict[name];
    }
    catch (KeyNotFoundException)
    {
        return null;
    }
}

最初の関数は2番目の関数よりも遅くする必要があるため、これら2つの関数のパフォーマンスに違いがあるかどうか興味がありました-辞書に値が含まれているかどうかを2回確認する必要があるのに対し、2番目の関数は辞書にのみアクセスする必要があるためです一度だけですが、実際には反対です:

1 000 000 の値のループ (100 000 が存在し、900 000 が存在しない場合):

最初の関数: 306 ミリ秒

2 番目の関数: 20483 ミリ秒

何故ですか?

編集:この質問の下のコメントでわかるように、存在しないキーが0個ある場合、2番目の関数のパフォーマンスは実際には最初の関数よりもわずかに優れています。ただし、存在しないキーが少なくとも 1 つ以上存在すると、2 つ目のキーのパフォーマンスは急速に低下します。

4

2 に答える 2

408

一方では、スタックをアンワインドする必要があるため、例外のスローは本質的にコストがかかり
ます。 一方、辞書内の値へのキーによるアクセスは、高速な O(1) 操作であるため安価です。

ところで:これを行う正しい方法は、使用することですTryGetValue

obj item;
if(!dict.TryGetValue(name, out item))
    return null;
return item;

これにより、ディクショナリへのアクセスが 2 回ではなく 1 回だけになります。
キーが存在しない場合に本当に戻りたいnull場合は、上記のコードをさらに単純化できます。

obj item;
dict.TryGetValue(name, out item);
return item;

キーが存在しない場合にTryGetValue設定itemされるため、これは機能します。nullname

于 2013-04-19T09:48:33.360 に答える