为什么快检查字典包含的关键,而不是捕捉的情况下它不会例外? [英] Why is it faster to check if dictionary contains the key, rather than catch the exception in case it doesn't?
问题描述
想象一下代码:
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;
}
}
我很好奇,如果有在性能差异这两种功能,因为第一个应该会比第二个更慢 - 因为它需要检查两次,如果字典中包含一个值,而第二个功能确实需要查阅字典只有一次,但WOW,它实际上是相反的:
I was curious if there is a difference in performance of these 2 functions, because the first one SHOULD be SLOWER than second one - given that it needs to check twice if the dictionary contains a value, while second function does need to access the dictionary only once but WOW, it's actually opposite:
环路为1 000 000的值(100 000现有的和900 000不存在的):
Loop for 1 000 000 values (with 100 000 existing and 900 000 non existing):
第一个功能:306毫秒
first function: 306 milliseconds
第二个功能:20483毫秒
second function: 20483 milliseconds
?这是为什么
编辑:正如你可以在下面这个问题的意见通知,第二个函数的表现实际上是在情况稍微比第一个更好的有0个不存在的键。但是,一旦至少有1个或多个不存在的钥匙,迅速第二个下降的表现。
As you can notice in comments below this question, the performance of second function is actually slightly better than first one in case there are 0 non existing keys. But once there is at least 1 or more non existing keys, the performance of second one decrease rapidly.
推荐答案
在一方面,抛出异常本质上是昂贵的,因为堆栈已被退绕等。
在另一方面,它的关键一本字典访问值是便宜,因为它是一个快速,O(1)操作
On the one hand, throwing exceptions is inherently expensive, because the stack has to be unwound etc.
On the other hand, accessing a value in a dictionary by its key is cheap, because it's a fast, O(1) operation.
BTW:要做到这一点,正确的方法是使用 TryGetValue
BTW: The correct way to do this is to use TryGetValue
obj item;
if(!dict.TryGetValue(name, out item))
return null;
return item;
这访问字典只有一次,而不是两次。结果
的如果你真的想刚刚返回空
如果该键不存在,上面的代码可以进一步简化:
This accesses the dictionary only once instead of twice.
If you really want to just return null
if the key doesn't exist, the above code can be simplified further:
obj item;
dict.TryGetValue(name, out item);
return item;
这工作,因为 TryGetValue
套项目
到空
如果与名称
不存在任何键。
This works, because TryGetValue
sets item
to null
if no key with name
exists.
这篇关于为什么快检查字典包含的关键,而不是捕捉的情况下它不会例外?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!