Containskey VS Try to Catch

I have a list of Vector2 Generated. I have to check with the dictionary to find out if they exist, this function is performed every tick.

which will work faster / better to do it this way?

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

Or should I stick to the norm?

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

Thanks for entering :)

Side note: (The value for the key is not relevant at the moment, or I would use TryGetValue instead of ContainsKey)

+4
dictionary c # try-catch
source share
4 answers

Definitely use the ContainsKey check; exception handling can add a lot of overhead .

Throwing exceptions can adversely affect performance. For code that usually fails, you can use design patterns to minimize performance issues.

Exceptions are not intended for conditions that you can verify.

I recommend reading the MSDN documentation on exceptions in general and exception handling in particular.

+13
source share

I know this is an old question, but just add some empirical data ...

Running 50,000,000 searches in a dictionary with 10,000 entries and comparing relative times to complete:

.. if each search succeeded:

  • direct (unchecked) startup takes 1.2 seconds.
  • A delayed (ContainsKey) start takes 2 seconds.
  • Running processed (try-catch) takes 1.21 seconds.

.. if 1 out of every 10,000 requests does not work:

  • A delayed (ContainsKey) start takes 2 seconds.
  • Running processed (try-catch) takes 1.37 seconds.

.. if 16 out of every 10,000 requests fail:

  • A delayed (ContainsKey) start takes 2 seconds.
  • Running processed (try-catch) takes 3.27 seconds.

.. If out of every 10,000 requests, 250 of them fail:

  • A delayed (ContainsKey) start takes 2 seconds.
  • Running processed (try-catch) takes 32 seconds.

.. therefore, the protected test will add constant overhead and nothing more, and the try-catch test will work almost as fast as without a test if it never works, but it kills the performance in proportion to the number of failures.

The code I used to run the tests:

 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); } } } 
+16
source share

Never use try / catch as part of your normal program path. It is really expensive and should only catch errors that you cannot prevent. ContainsKey is the way here.

Side Note: None. You would not do that. If the value matters, you check with the ContainsKey if it exists and retrieves it if it is. Do not try / catch.

0
source share

Side note: (The value for the key is not relevant at the moment, or I would use TryGetValue instead of ContainsKey)

The answer you accepted is correct, but just to add, if you only care about the key and not the value, maybe you are looking for a HashSet , not a Dictionary ?

Also, your second piece of code is a method that literally adds a null value. Just use ToCheck.ContainsKey(Position) , do not make a method that just calls this method and returns its value, but does nothing.

0
source share

All Articles