包含密钥VS尝试捕获

Dus*_*sty 8 c# dictionary try-catch containskey

我有一个Vector2的生成列表我必须检查一个字典,看看它们是否存在,这个函数每次滴答都会被执行.

这样做会跑得最快/做得更好?

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

或者我应该坚持常态?

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

谢谢你输入:)

旁注:(此时密钥的值无关紧要,或者我将使用TryGetValue而不是ContainsKey)

小智 24

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

在包含10,000个条目的字典上运行50,000,000个查找并比较完成的相对时间:

..如果每次查找都成功:

  • 直接(未经检查)运行需要1.2秒
  • 保护(ContainsKey)运行需要2秒
  • 处理(try-catch)运行需要1.21秒

..如果每10,000个观察中有1个失败:

  • 保护(ContainsKey)运行需要2秒
  • 处理(try-catch)运行需要1.37秒

..如果每10,000个观察中有16个失败:

  • 保护(ContainsKey)运行需要2秒
  • 处理(try-catch)运行需要3.27秒

..如果每10,000个查找中有250个失败:

  • 保护(ContainsKey)运行需要2秒
  • 处理(try-catch)运行需要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);
      }

   }
}
Run Code Online (Sandbox Code Playgroud)

  • +1正如我所想.如果你想要原始性能并且你确信查找很少会失败,那么使用`try-catch`而不是`ContainsKey`要好得多. (2认同)

McG*_*gle 16

绝对使用ContainsKey支票; 异常处理可能会增加很大的开销.

抛出异常会对性能产生负面影响.对于常规失败的代码,您可以使用设计模式来最小化性能问题.

例外情况并不适用于您可以检查的条件.

我建议您阅读MSDN文档例外一般,和异常处理尤其如此.

  • 在某些情况下调用你知道的方法会引发异常就像是闭着眼睛开车.有更好的方法可以发现道路的引导位置,而不是等到你撞到或开过来的东西. (4认同)
  • @Dusty,我长期不得不纠正这种误解.这可能是由于其他语言(例如,Python)强烈鼓励使用异常作为控制流.但就.NET而言(以及JVM,就此问题而言),除非代表无法恢复的场景,否则不应抛出异常. (2认同)

归档时间:

查看次数:

3318 次

最近记录:

13 年,11 月 前