0

I have a question about best practices regarding exceptions. This weekend, I was working on my little game, and I found myself wondering if it's best to use IF or a TRY to validate NULL... Here are the two variants of a same function:

This is my code using an IF

//Using IF
void ParseGamePad() {
    GamePadData pad = GamePad.GetDate(0);
    foreach(var btn in Enum.GetValues(GamePad.BUTTONS)) {
        if(myArray.ContainsKey(btn))
            if(myArray[btn]!=null)
                myArray[btn](); //Execute function reference in array
    }
    return;
}

Here's what the code is like with a Try{}Catch

//Using TRY
void ParseGamePad() {
    GamePadData pad = GamePad.GetDate(0);
    foreach(var btn in Enum.GetValues(GamePad.BUTTONS)) {
        try {
            myArray[btn](); //Execute function reference in array
        } catch(System.Exception e) {
            // Nothing to do here
        }
    }
    return;
}

The way I figure it, the IF block is quicker than the TRY block when the element doesn't exist in the array, whereas the TRY is quicker when the element exists, but slower when an Exception is caught.

What would you guys do?

PS: This project is on an embedded system, so CPU and RAM are a factor.

SsJVasto
  • 486
  • 2
  • 13
  • 1
    what type is `myArray`? – Daniel A. White Jun 23 '14 at 12:42
  • 2
    is myArray a Dictionary? (because an array doesn't have a method ContainsKey) – Dennis_E Jun 23 '14 at 12:43
  • yes, it is something like `Dictionary` where func_call is a delegate function reference. – SsJVasto Jun 23 '14 at 12:47
  • if an exception is thrown, then .Net needs to start unwraping the stack, which takes about a hour... never use exception for bussiness logic, unless it's some sort of a catastrophic bussiness error, and even that rarely makes sense... – AK_ Jun 23 '14 at 12:49
  • Thanks for the downvotes guys, I'll know not to ask questions 'round here anymore :) – SsJVasto Jun 23 '14 at 13:19
  • 1
    @SsJVasto I really don't get the down votes, it's a perfectly valid question... – AK_ Jun 23 '14 at 15:48

4 Answers4

5

Do not use exceptions for program flow - they are meant to catch exceptional cases. If myArray[btn] should never be null then throwing an exception when it is would be fine, but catching it to see if it is null is not a best practice (plus, catching Exception would cover a lot of possible conditions, not just when the value is null or not found).

As far as performance goes, checking an object for null should be extremely cheap, so I would not expect any significant performance difference in the normal case.

You could reduce the number of index lookups by two (which could make a significant performance improvement) by using TryGetValue:

foreach(var btn in Enum.GetValues(GamePad.BUTTONS)) {
    Action<Button> func;   // Guessing on the type here
    bool found = myArray.TryGetValue(btn, out func);
    if(found && func != null)
        func(); //Execute function reference in array
}
D Stanley
  • 149,601
  • 11
  • 178
  • 240
2

You shouldn't rely on Exceptions as a proper flow for your system, as they will have performance effects. As null checks are a chearp an exception which may propogate up the call chain (which may take a while depending on your stack depth), you should go with the nullity check.

I would also say that Exceptions should be kept for unexpected behavior. You might decide that a Dictionary holding a null value is exceptional behavior in your program, and that's fine, as it is opinion based. I would definitely advised against it.

You should go ahead and check How expensive are exceptions in C#? for excellent links on exceptions and performance.

Community
  • 1
  • 1
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
2

If myArray is a Dictionary as I suspect, you can use TryGetValue.

Catching an exception is not a good solution in this case.

The first option has a (very) slight problem, because you're looking for the item twice, so TryGetValue is what I would use. (If myArray is a Dictionary, then myArray is not a good name.)

Dennis_E
  • 8,751
  • 23
  • 29
1

At least, I would not catch Exception but a more special exception type.

adjan
  • 13,371
  • 2
  • 31
  • 48
  • Yeah, I don't have the actual code at hand right now, but the exception caught is `System.Collections.Generic::KeyNotFoundException` – SsJVasto Jun 23 '14 at 14:41