Exceptions handle exceptional cases; that is, cases that do not fall into the "happy path" of normal program execution. Given this very important caveat, it is generally acceptable, and in fact, expected, to use try/catchtry/catch
in cases where (a) something can fail, and (b) you know what to do when it does.
The primary situation in which you would not use try-catchtry-catch
is when knowing the success or failure of a method is at least as important as the actual result of the operation. An example is string parsing;parsing: many times, it's at least as useful to know if a string consists of a number or not, than what the number actually is. Thus .NET thus.NET
provides "TryParse" flavors of the Parse functions built into the primitive types. They allow you to structure your code with a simple decision at the beginning of an if/elseif/else
fork, that then determines entry into one or the other of the code blocks.
For instance, say DoSomething()DoSomething()
's success determines whether to print "Yes" or "No" to the console. Both are "normal" things for the program to do. You could write it like this:
... but there are a couple of problems;problems: first, from a design standpoint, it's not obvious without comments that DoSomething()DoSomething()
is a decision being made. Second, DoSomething()DoSomething()
may not be the only thing in the trytry
block that could throw an exception. Let's say another developer added some additional code that they need to run when DoSomethingDoSomething
succeeds:
Now, you have a scenario in which DoSomethingElse()DoSomethingElse()
could fail after DoSomething()DoSomething()
succeeded, and the result to the end user-user from one input would be the very confusing:
The concept that DoSomethingDoSomething
is the criteria of a decision between two "normal" execution paths is much clearer in the above code. And, your desired logic flow is enforced no matter what; If DoSomething()DoSomething()
succeeds, the user will never see "No" displayed on screen no matter what DoSomethingElse()DoSomethingElse()
does.
In most other cases, try-catchtry-catch
is preferred, for one or more of the following reasons:
- try-catch allows you to use the return value of a method for what is was conceptually designed to do; return the result of the operation, instead of a status code indicating whether a valid result is contained in an output or reference parameter that is the REAL product of the method.
try-catch
allows you to use the return value of a method for what it was conceptually designed to do; return the result of the operation, instead of a status code indicating whether a valid result is contained in an output or reference parameter that is the REAL product of the method.
- try-catch allows for more object-oriented error-handling, as was mentioned, by avoiding the use of "magic numbers"; you don't have to know that return code -2 of this method is an error that an argument was null, you just catch an ArgumentNullException. And, you can catch that same ArgumentNullException thrown from any method that cares whether one of its passed parameters was null, instead of having to know that this method would return -2 and another method returns -3 in the same situation.
try-catch
allows for more object-oriented error-handling, as was mentioned, by avoiding the use of "magic numbers"; you don't have to know that return code -2 of this method is an error that an argument was null
, you just catch
an ArgumentNullException
. And, you can catch
that same ArgumentNullException
thrown from any method that cares whether one of its passed parameters was null
, instead of having to know that this method would return -2 and another method returns -3 in the same situation.
- By that token, try-catch helps to standardize the expected behavior in a particular exceptional case. If you pass a null parameter to a method that requires that parameter to not be null, you will get an ArgumentNullException, and it is usually bad practice to throw any other exception or to assume some base case that equates null with a discrete value.
By that token, try-catch
helps to standardize the expected behavior in a particularly exceptional case: If you pass a null
parameter to a method that requires that parameter to not be null
, you will get an ArgumentNullException
, and it is usually bad practice to throw any other exception or to assume some base case that equates null
with a discrete value.
- try-catch isn't limited to calling methods; you can "try" a possible division-by-zero operation inline in your code and catch the exception thrown by the runtime should it occur.
try-catch
isn't limited to calling methods; you can "try" a possible division-by-zero operation inline in your code and catch
the exception thrown by the runtime should it occur.
- try-catch isn't limited to one method at a time; you can, with minimal additional code, handle exceptions from a series of several methods, and abort processing, without having to examine the most recent return code of each method you call.
try-catch
isn't limited to one method at a time; you can, with minimal additional code, handle exceptions from a series of several methods, and abort processing, without having to examine the most recent return code of each method you call.