2

What is the better approach when handling errors - throwing it as an exception or returning a an object that contains the error and its details?

I'm thinking what is the better approach to notifying errors - in terms of system resources, coding practices and overall enterprise practices ?

I've seen in most cases, the sample code throws a custom exception containing the error information. But I was thinking if it was better to just return an object instantiated from a class (for example: class DatabaseError)?

I believe throwing exceptions in C# can be resource intensive and this would involve having (possibly) a lot of try-catch blocks.

Thanks!

John Saunders
  • 160,644
  • 26
  • 247
  • 397
codex10
  • 105
  • 1
  • 10
  • 1
    What kind of errors are you talking about? Expected? Unexpected? Situations that are _completely_ incorrect in your model? – Oded Jan 28 '12 at 17:59
  • Possible duplicate of [tag:exception-handling]. – John Saunders Jan 28 '12 at 18:23
  • @oded - nothing specific really, just a general error. The thought i had was how to tell the caller of the function that an error occurred and info on the error. I thought throwing an exception was a bit too much. but seems like its the best and recommended way to go. – codex10 Jan 28 '12 at 19:56
  • @John Saunders - thanks for the link. Seems like a lot of answers already to this same question. Sorry i didnt bother to check first, I thought it was a pretty beginner's question really. – codex10 Jan 28 '12 at 19:57
  • There are many beginners here. Any beginner's question has already been asked. – John Saunders Jan 28 '12 at 23:24

3 Answers3

2

DO NOT return error codes.

Exceptions are the primary means of reporting errors in frameworks.

-Framework Design Guidelines

See that excellent book for details and for ways to deal with performance.

TrueWill
  • 25,132
  • 10
  • 101
  • 150
2

Exceptions are generally considered to be the preferred mechanism for relaying error conditions up the application chain to where they can be dealt with and managed in such a way that they do not cause the application to fail completely and terminate.

However, it is also generally considered poor practice to use the exception-handling mechanism as a logic path - that is, to make the catching of an error condition a prerequisite for later correct or alternative functionality (e.g. to attempt to open a file which may or may not exist, catch the exception if it does not exist, and present a file-browser dialog as a consequence - in this example, the 'NOT FOUND' error condition should be detected before attempting to open the file rather than regarding the exception path as the route by which the user is asked to locate it).

Eight-Bit Guru
  • 9,756
  • 2
  • 48
  • 62
  • thanks for the insight Jonners. So in this thought, whats the approach in telling the caller that something isn't right and some info about it (ex: the file they're attempting to open is not found). so actually, it comes down to how i tell the caller there's an error and here's the info. Most seem to point using exception handling, but I also appreciate your point being its not good practice to use exceptions as a catch-all for notifying trivial errors. – codex10 Jan 28 '12 at 20:04
  • 1
    @codex10 - I think Jonners is referring to the Tester-Doer Pattern - if there's a way to check for an error condition **before** calling a method, it's often good practice to do so. There's also the Try-Parse Pattern. – TrueWill Jan 28 '12 at 20:13
  • @codex10 - yep, this is it precisely. The point is not to restrict error information being passed to the user, but to try to ensure that the exception-handling mechanism isn't used as part of the logical flow - test for probable fail conditions prior to the action, and then use the exception mechanics to alert the user when something goes still goes wrong anyway. – Eight-Bit Guru Jan 28 '12 at 22:14
2

When the caller is expecting that a condition may occur, it is best to inform the caller of that condition via return code. When a condition occurs which the caller is not expecting, it is best to inform the caller via an exception.

Because most languages do not provide any means for a called routine to 'magically' know what the caller is expecting, the only way a routine will know what the caller is expecting is for the caller to tell it. There are a few patterns I would suggest:

  1. Have both a "DoSomething" method and a "TryDoSomething" method. The former will throw an exception if it cannot achieve the intended objective, while the latter will throw an exception.
  2. Use a single method with a Boolean or enumeration parameter which indicates whether a routine should behave as a "Try" or "Do" method. This is often useful in conjunction with small "DoSomething" and "TryDoSomething" methods which call the combined routine passing an appropriate parameter value. Although many implementations would make the combined routine protected, having it public may allow it to be called from another "Do or Try" routine, passing the ThrowOnFailure value from the other routine to the inner routine.
  3. Have a single method with overloads that include or do not include a 'ref' parameter that will be used to indicate success or failure. The version of the function with the parameter will use it to indicate failure (without throwing an exception), while the overload without it will throw an exception in the failure case.
  4. Have a single method with a delegate which should be invoked in case of failure. Conceptually, this is an even better approach than passing a Boolean parameter, since the delegate can not only throw an exception the invoking code will be prepared to catch; it can also set flags or take other action so when the invoking code catches the exception, it can be sure what really happened. Unfortunately, figuring out the optimal form for the delegate, including what parameters it should take, is tricky.

Approach #1 seems to be Microsoft's recommended pattern, though I think #2 can help avoid duplicate coding. Approach #3 would be similar to a convention used in Borland Pascal some years back, that worked out relatively intuitively. Approach #4 would seem the nicest, but I haven't figured out how best to do it practically.

supercat
  • 77,689
  • 9
  • 166
  • 211