C# – Is onError Handler Better Than Exceptions?

c

I understand that exception in program means that something unpredictable happened (but not so bad to unavoidably crash the application!). The try-catch-finally sequence makes me sad because the program is harder to read (one more level of curly brackets) and harder to understand (jump from anywhere to catch in case of exception happened, it is deprecated GOTO).

Since we have OOP, I suggest to create proxy class which in case of exception consumes it silently, returns some default value and fires onError event. So if we propagate exception, we have onError call instead, and the two disadvantages mentioned above are solved. See the example in C#:

Standard exception attitude

  class Computer {
    // let's say we need to propagate exception and decide what to do lately
    public int divide(int a, int b) {
      int result = a / b;
      return result;
    }
  }

  class Program {
    public static void Main() {
      Computer c = new Computer();
      try {
        Console.WriteLine(c.divide(1, 0));
      }
      catch(ArithmeticException e) {
        // we are teleported here from the middle of Computer.divide method!
        // do something
      }
    }
  } // three levels of brackets (without namespace) in such trivial example??

onError handler attitude

  class ProxyComputer {
    private Computer c = new Computer();
    // it is not virtual, can not be overriden
    public int divide(int a, int b) {
      // alas, exceptions are standard, but we can stop them in this class
      try {
        return c.divide(a, b);
      }
      catch(ArithmeticException e) {
        this.onError(e);
      }
    }

    protected virtual void onError(Exception e) {
      // do nothing
    }
  }

  class MoreStrictComputer : ProxyComputer {
    protected override void onError(Exception e) {
      // mail to IT department, revert all transactions etc.
      Console.WriteLine("I can't seem to do that");
    }
  }

  class Program {
    public static void Main() {
      ProxyComputer pc = new ProxyComputer();
      MoreStrictComputer msc = new MoreStrictComputer();
      // fires onError instead of exception
      Console.WriteLine(pc.divide(1, 0)); // no problem
      Console.WriteLine(msc.divide(1, 0)); // this time it won't be so easy
    }
  } // only two levels of brackets

Often I see empty (or trivial) catch blocks. This means programmers often consider exception as no problem situation, but with standard exception attitude, they still have to bother with try-catch. The second attitude makes it optional.

So the question is: Which solution would you prefer? Is this some kind of pattern or am I missing something?

Edit As Paul Equis suggests, throw e; should be default onError behavior, not do-nothing silence swalowing.

Best Answer

I agree with Paul Equis's answer that exceptions should be preferred, but with a caveat. One major feature of exceptions is that they break control flow. This is usually desirable, but if it isn't then some other pattern might be useful for augmenting the exception system.

For example, suppose you're writing a compiler. Exceptions might not be the best choice here, because throwing an exception stops the compile process. This means that only that first error would be reported. If you want to keep reading the source code in order to try and find more errors (as the C# and VB compilers do), then some other system is needed for reporting errors to the outside world.

The easiest way to take care of that would be saving the exceptions to a collection and then returning it. However, using an OnError delegate might be worthwhile if you want to give the caller an opportunity to give advice on how to proceed after each error. That sounds like an uncommon scenario to me, though. If you're not asking the caller to really micro-manage error handling, then using some flags to specify error-handling behavior would be less fiddly to work with.

Related Topic