Containskey VS Try Catch



我有一个Vector2的Generated列表。我必须对照字典检查它们是否存在,这个函数每次都会执行。

这样做哪个跑得最快/更好?

public static bool exists(Vector2 Position, Dictionary<Vector2, object> ToCheck)
{
try
{
object Test = ToCheck[Position];
return (true);
}
catch 
{
return (false);
}           
}

还是我应该坚持规范?

public static bool exists(Vector2 Position, Dictionary<Vector2, object> ToCheck)
{
if (ToCheck.ContainsKey(Position))
{
return (true);
}
return (false);
}

感谢您的输入:)

旁注:(密钥的值在这一点上无关紧要,否则我会使用TryGetValue而不是ContainsKey)

我知道这是一个老问题,但只是添加一些经验数据。。。

在一本有10000个词条的词典上运行50000000次查找,并比较完成的相对时间:

如果每次查找都成功:

  • 直接(未检查)跑步需要1.2秒
  • 有防护的(ContainsKey)跑步需要2秒
  • 一次有把握的(尝试接球)跑需要1.21秒

。。如果每10000次查找中就有1次失败:

  • 一次有保护的(ContainsKey)跑步需要2秒
  • 一次有把握的(尝试接球)跑需要1.37秒

。。如果每10000次查找中有16次失败:

  • 一次有保护的(ContainsKey)跑步需要2秒
  • 一次有把握的(尝试接球)跑需要3.27秒

。。如果每10000次查找中有250次失败:

  • 一次有保护的(ContainsKey)跑步需要2秒
  • 一次有把握的(尝试接球)跑需要32秒

。。因此,有保护的测试将增加恒定的开销,而try-catch测试的运行速度几乎与没有测试一样快(如果它从未失败),但会随着失败次数的增加而降低性能。

我用来运行测试的代码:

using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{  Test(0);
Test(1);
Test(16);
Test(250);
}
private static void Test(int failsPerSet)
{  Dictionary<int, bool> items = new Dictionary<int,bool>();
for(int i =  0; i < 10000; i++)
if(i >= failsPerSet)
items[i] = true;
if(failsPerSet == 0)
RawLookup(items, failsPerSet);
GuardedLookup(items, failsPerSet);
CaughtLookup(items, failsPerSet);
}
private static void RawLookup
(  Dictionary<int, bool> items
,  int             failsPerSet
){ int                   found = 0;
DateTime              start ;
Console.Write("Raw     (");
Console.Write(failsPerSet);
Console.Write("): ");
start = DateTime.Now;
for(int i = 0; i < 50000000; i++)
{  int pick = i % 10000;
if(items[pick])
found++;
}
Console.WriteLine(DateTime.Now - start);
}
private static void GuardedLookup
(  Dictionary<int, bool> items
,  int             failsPerSet
){ int                   found = 0;
DateTime              start ;
Console.Write("Guarded (");
Console.Write(failsPerSet);
Console.Write("): ");
start = DateTime.Now;
for(int i = 0; i < 50000000; i++)
{  int pick = i % 10000;
if(items.ContainsKey(pick))
if(items[pick])
found++;
}
Console.WriteLine(DateTime.Now - start);
}
private static void CaughtLookup
(  Dictionary<int, bool> items
,  int             failsPerSet
){ int                   found = 0;
DateTime              start ;
Console.Write("Caught  (");
Console.Write(failsPerSet);
Console.Write("): ");
start = DateTime.Now;
for(int i = 0; i < 50000000; i++)
{  int pick = i % 10000;
try
{  if(items[pick])
found++;
}
catch
{  
}
}
Console.WriteLine(DateTime.Now - start);
}
}
}

一定要使用ContainsKey检查;异常处理可能会增加很大的开销。

引发异常会对性能产生负面影响。对于经常失败的代码,可以使用设计模式来最大限度地减少性能问题。

异常不适用于您可以检查的条件。

我建议阅读MSDN文档中关于异常的一般内容,尤其是关于异常处理的内容。

永远不要将try/catch作为常规程序路径的一部分。它确实很昂贵,而且应该只捕获无法防止的错误。ContainsKey是去这里的路。

旁注:不,你不会的。如果值很重要,请使用ContainsKey检查它是否存在,如果存在,则检索它。不要尝试/抓住。

旁注:(密钥的值在这一点上无关紧要,否则我会使用TryGetValue而不是ContainsKey)

您接受的答案是正确的,但补充一下,如果您只关心密钥而不关心值,那么您可能正在寻找HashSet而不是Dictionary

此外,您的第二个代码片段是一个添加零值的方法。只需使用ToCheck.ContainsKey(Position),不要生成一个只调用该方法并返回其值但不执行其他操作的方法。

相关内容

  • 没有找到相关文章

最新更新