4
\$\begingroup\$

It doesn't happen often, but I sometimes come across cases where I miss Java's checked exceptions, especially in medium sized methods of about 30 odd lines that call outward. Often, the following pattern emerges:

bool Foo(){
  LibType l1 = new LibType("bla");
  LibType2 smt = l1.bar("context");
  ...
  ...
}

and I want to know when which part of the function has thrown an exception. I know that the external library Lib exposes LibException, and that l1.bar should throw that in some case. But I have no language level guarantees. What I would like is

bool Foo(){
  try {
  LibType l1 = new LibType("bla");
  LibType2 smt = l1.bar("context");
  ...
  ...
  ...
  return true;
  } catch (LibException le){
    //take appropriate action by flogging the library
    //log that the exception has occurred in Lib while trying to Foo.
    return false;
  } 
}

but I can't be sure there will not be any other exceptions. In fact, this doesn't even compile, as not all code paths return a value, so I will have to catch a more generic Exception, which could have come from any part off the method.

What I have done, is create a wrapper function, to ensure that all exceptions will be LibExceptions:

private T Wrapped<T, E>(Func<Exception, E> buildException, Func<T> f) where E : Exception {
  try { return f(); }
  catch (E) {
    throw;
  }
  catch (Exception ee) {
    throw (buildException(ee));
  }
}

so I can now be ensured a block can only throw the wrapping exception by wrapping it like so

bool Foo(){
  try {
  LibType2 smt = Wrapped(e => new LibException(String.Format("Unexpected exception: {0}", e.Message)), () => {
    LibType l1 = new LibType("bla");
    return l1.bar("context");
  });
  ...
  ...
  ...
  return true;
  } catch (LibException le){
    //take appropriate action by flogging the library
    //log that the exception has occurred in Lib while trying to Foo.
    return false;
  } 
}

I see smells aplenty though, and I am bending stuff in ways I get the feeling it wasn't designed to bend. Is this basically OK? are there things to be on the lookout for? Or is this one off those stop trying to be clever, and slowly back away from the computer moments?

\$\endgroup\$
  • 3
    \$\begingroup\$ “this doesn't even compile, as not all code paths return a value” That's not true, the code you posted should compile just fine. \$\endgroup\$ – svick Apr 2 '13 at 18:01
6
\$\begingroup\$

I really don't see any advantage in your approach.

If you want to catch specific exception from a specific part of the code, do that:

bool Foo(){
  try {
    LibType l1 = new LibType("bla");
    LibType2 smt = l1.bar("context");
  } catch (LibException le){
    //take appropriate action by flogging the library
    //log that the exception has occurred in Lib while trying to Foo.
    return false;
  } 
  ...
  ...
  ...
  return true;
}

When a piece of code encounters an exception you didn't expect, it's usually not a good idea to try to handle it anyway. Unexpected exception means your program is now in an unknown, possibly horribly broken state. The safe thing in that case is to crash the application.

\$\endgroup\$
1
\$\begingroup\$

Just to build on what @svick said, this is definitely not a good way to handle things.

If you want to catch all exceptions, simply catch (Exception ex). If you don't want to catch everything, then only catch the specific types you want. There's also the finally block which you can use to do any cleanup which is necessary, regardless of whether or not you've handled the exception.

\$\endgroup\$
0
\$\begingroup\$

You can get some of the help Java checked exceptions give you by using Resharper and a plugin called Exceptional.

It analyzes the XML docs and is able to add catch blocks for each documented exception. You'll have to build it yourself though, it's not very well maintained. (You'll even have to grab a fork)

That being said, to be able to clean up, I'd rather just catch Exception in addition to LibException. Other exceptions are exceptions, and should be thrown so you can fix the problem rather than cure the symptom.

try
{
    // whatever
}
catch(LibException)
{
    // do LibException specific stuff
    // clean up
}
catch
{
    // clean up
    throw; // crash the system, you shouldn't get this exception in the next version
}
\$\endgroup\$
  • 1
    \$\begingroup\$ If you want to do some cleanup, use finally, not catch with throw; inside it. \$\endgroup\$ – svick Apr 3 '13 at 18:35
  • \$\begingroup\$ As far as I understood, he'd like to clean up attempted stuff if something went wrong, not if it succeeded. Finally would for instance dispose any unmanaged resources. (Of course he could benefit from using transactions, but that's another topic) \$\endgroup\$ – Lars-Erik Apr 5 '13 at 12:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.