Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should TryFoo ever throw an exception?

Tags:

.net

exception

A common pattern in the .NET Framework is the TryXXX pattern (I don't know if that's what they really call it), in which the called method attempts to do something, returning True if it was successful, or False if the operation failed. A good example is the generic Dictionary.TryGetValue method.

Documentation for these methods say that they will not throw exceptions: that failure will be reported in the method return value. All good so far.

I recently encountered two different circumstances in which .NET Framework methods that implement the TryXXX pattern threw exceptions. See Bug in System.Random constructor? and Uri.TryCreate throws UriFormatException? for details.

In both cases, the TryXXX method called other methods that threw unexpected exceptions, and those exceptions escaped. My question: does this break the implied contract of not throwing exceptions?

Put another way, if you were writing TryFoo, would you guarantee that exceptions cannot escape, by writing it like this?

public bool TryFoo(string param, out FooThing foo)
{
    try
    {
        // do whatever
        return true;
    }
    catch
    {
        foo = null;
        return false;
    }
}

It's tempting, because that guarantees no exceptions will escape, thereby honoring the implied contract. But it's a bug hider.

My gut feeling, based on my experience, says that this is a really bad idea. But if TryFoo lets some exceptions escape, then what it's really saying is, "I won't throw any exceptions that I know how to handle," and then the whole idea of the contract "I won't throw exceptions" is thrown out the window.

So, what's your opinion? Should TryFoo handle all exceptions, or just those that it's expecting to happen? What's your reasoning?

like image 955
Jim Mischel Avatar asked Jul 22 '09 17:07

Jim Mischel


1 Answers

It depends. TryParseFoo should catch all parsing exceptions for stuff like null or misformatted strings. But there are also unrelated exceptions (ThreadAbortException, say) that should not be automatically quieted.

In Python (bear with me), you can cause a lot of trouble by catching KeyboardInterrupt exceptions, which basically means your program keeps running even if you Ctrl-C out of it.

My rule of thumb is that you should use TryFoo when you want to Foo without cleaning up your inputs. If TryFoo catches errors unrelated to Fooing your input, it's being too aggressive.

like image 101
ojrac Avatar answered Oct 19 '22 23:10

ojrac