2012-09-14 29 views
4

我有一個Vector2的生成列表,我必須檢查一個字典,看看它們是否存在,這個函數會在每個tick中執行。Containskey VS Try Catch

哪個運行速度最快/是否最好這樣做?

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); 
    } 

感謝輸入:)

側面說明:(該鍵的值不會在這點事或我會用替代的containsKey TryGetValue)

+2

你怎麼可能會寫第二個方法是什麼?你真的用另一個函數調用來包裝函數調用,什麼都不做。而不是調用該函數,調用者可以直接調用「ContainsKey」 – Servy

+1

是的,只需返回'ToCheck.ContainsKey(Position)'。 – nawfal

+0

可能的重複[爲什麼檢查字典是否包含密鑰更快,而不是在發生異常時檢查它?](http://stackoverflow.com/questions/16101795/why-is-it-faster檢查是否字典包含的關鍵而不是趕上) – nawfal

回答

13

絕對使用ContainsKey檢查;異常處理可以add a large overhead

投擲異常會對性能產生負面影響。對於經常失敗的代碼,您可以使用設計模式來最大限度地減少性能問題。

例外並不意味着您可以檢查的條件。

我推薦閱讀關於exceptions generally和特別是exception handling的MSDN文檔。

+4

在某些情況下調用一個你知道拋出異常的方法是l你閉着眼睛開着你的車。有更好的方法來發現路的引導,而不是等到你碰到或開車過東西。 – Dan

+1

+1。除了錯誤的代碼流構造和巨大的運行時間成本以外,異常使得調試更加困難(假設您在「異常時檢查異常」時進行中斷......這是避免頻繁執行的代碼中的異常的好主意)。 –

+0

感謝您的信息,幫助很多,我想知道,因爲我在另一篇文章(我不記得主要想法)閱讀,有人迴應說試試捕捉幾乎不會影響性能。 – Dusty

0

切勿將try/catch用作常規程序路徑的一部分。這是非常昂貴的,應該只捕捉你無法預防的錯誤。 ContainsKey是去這裏的路。

旁註:不,你不會。如果值與ContainsKey檢查,如果它存在並檢索它,如果它確實。不要嘗試/捕捉。

0

側面說明:(該鍵的值不會在這點事或我會用替代的containsKey TryGetValue)

你接受的答案是正確的,但只是添加,如果你只關心鑰匙而不是價值,也許你正在尋找一個HashSet而不是一個Dictionary

此外,你的第二個代碼片段是一個方法,它實際上增加了零值。只需使用ToCheck.ContainsKey(Position),不要創建一個方法,只調用該方法並返回其值,但別無其他。

+0

我確實需要這些值,它用於生成地圖。附註是由於我看到很多人問「爲什麼不使用TryGetValue」,當它與問題無關時。但是如果有需要的話,我會記住HashSet的,謝謝:) – Dusty

16

我知道這是一個老問題,但只是爲了增加一點經驗數據...

運行5000萬上一本字典有10000條查詢窗口和比較相對時間來完成:

。每一個。如果查找成功:

  • 直(未選中)運行需要1.2秒
  • 一個守衛(的containsKey)運行需要2秒
  • 處理(try-catch)運行需要1。21秒

..如果1出每10000查詢UPS的失敗:

  • 一個守衛(的containsKey)運行需要2秒
  • 一個處理(的try-catch)運行需要1.37秒

..如果16出每10000查詢UPS的失敗:

  • 有人看守(的containsKey)運行需要2秒
  • 一個處理(的try-catch)運行需要3.27秒

..如果250出每10000查詢UPS的失敗:

  • 一個守衛(的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); 
     } 

    } 
} 
+0

+1科學的方法! – GenericJon

+0

謝謝,這太棒了! – Dusty

+0

在現實情況下,'ContainsKey'總是更好。 – nawfal