Exception Handling – Reasons to Return Exception Objects

exception handlingexceptions

This question is intended to apply to any OO programming language that supports exception handling; I am using C# for illustrative purposes only.

Exceptions are usually intended to be raised when an problem arises that the code cannot immediately handle, and then to be caught in a catch clause in a different location (usually an outer stack frame).

Q: Are there any legitimate situations where exceptions are not thrown and caught, but simply returned from a method and then passed around as error objects?

This question came up for me because .NET 4's System.IObserver<T>.OnError method suggests just that: exceptions being passed around as error objects.

Let's look at another scenario, validation. Let's say I am following conventional wisdom, and that I am therefore distinguishing between an error object type IValidationError and a separate exception type ValidationException that is used to report unexpected errors:

partial interface IValidationError { }

abstract partial class ValidationException : System.Exception
{
    public abstract IValidationError[] ValidationErrors { get; }
}

(The System.Component.DataAnnotations namespace does something quite similar.)

These types could be employed as follows:

partial interface IFoo { }  // an immutable type

partial interface IFooBuilder  // mutable counterpart to prepare instances of above type
{
    bool IsValid(out IValidationError[] validationErrors);  // true if no validation error occurs
    IFoo Build();  // throws ValidationException if !IsValid(…)
}

Now I am wondering, could I not simplify the above to this:

partial class ValidationError : System.Exception { }  // = IValidationError + ValidationException

partial interface IFoo { }  // (unchanged)

partial interface IFooBuilder
{
    bool IsValid(out ValidationError[] validationErrors);
    IFoo Build();  // may throw ValidationError or sth. like AggregateException<ValidationError>
}

Q: What are the advantages and disadvantages of these two differing approaches?

Best Answer

Are there any legitimate situations where exceptions are not thrown and caught, but simply returned from a method and then passed around as error objects?

If it is never thrown then it's not an exception. It is an object derived from an Exception class, though it does not follow the behavior. Calling it an Exception is purely semantics at this point, but I see nothing wrong with not throwing it. From my perspective, not throwing an exception is the exact same thing as an inner-function catching it and preventing it from propagating.

Is it valid for a function to return exception objects?

Absolutely. Here is a short list of examples where this may be appropriate:

  • An exception factory.
  • A context object that reports if there was a previous error as a ready to use exception.
  • A function that keeps a previously caught exception.
  • A third-party API that creates an exception of an inner type.

Is not throwing it bad?

Throwing an exception is kind of like: "Go to jail. Do not pass Go!" in the board game Monopoly. It tells a compiler to jump over all source code up to the catch without executing any of that source code. It doesn't have anything to do with errors, reporting or stopping bugs. I like to think of throwing an exception as a "super return" statement for a function. It returns execution of the code to somewhere much higher up than the original caller.

The important thing here is to understand that the true value of exceptions is in the try/catch pattern, and not the instantiation of the exception object. The exception object is just a state message.

In your question you seem to be confusing the usage of these two things: a jumping to a handler of the exception, and the error state the exception represents. Just because you took an error state and wrapped it in an exception does not mean you are following the try/catch pattern or its benefits.

Related Topic