Why Are Exceptions Not Checked in .Net

Why are Exceptions not Checked in .NET?

Because the response to checked exceptions is almost always:

try {
// exception throwing code
} catch(Exception e) {
// either
log.error("Error fooing bar",e);
// OR
throw new RuntimeException(e);
}

If you actually know that there is something you can do if a particular exception is thrown, then you can catch it and then handle it, but otherwise it's just incantations to appease the compiler.

checked and unchecked exception in .NET

In Java, checked and unchecked exceptions don't exactly map to a fatal or non-fatal error. A checked exception explicitly is stating that the exception may be thrown and someone must catch it (to try to handle it or throw it up the stack), but there is no guarantee that the error may not be fatal (i.e. a syntax error in an SQL query will throw an SQLException and will likely be fatal, but it is a checked exception). An unchecked exception just means that someone doesn't need to catch it, but you still can if you want. It would typically indicate a programming error. Java Errors typically indicate things that are unrecoverable problems (such as an OutOfMemoryError).

The C# design of unchecked exceptions just means you don't need to catch the exceptions, and if uncaught will crash the application. Checked vs unchecked exceptions has been a long standing debate in the development community and there are pros and cons to both. Typically though, you can't do something about an exception and it frequently just ends up getting logged rather than handled, so C# made exceptions unchecked. When you can handle them (for example, if you want to retry an IO operation), you can still catch them and retry.

checked exception in C#

C# does not support checked exceptions. You can read up on why the original design did not include checked exceptions.

Link: The Trouble with Checked Exceptions

What kind of Exceptions cannot be handled?

Jeffrey Richter made several good points on this topic in his book CLR via C#, part "Trading Reliability for Productivity".

BTW, you can catch and handle OutOfMemmory:

For some reason that I can’t quite explain, this attention to detail is not done when writing
code for the .NET Framework. Getting an out-of-memory situation is always possible
and yet I almost never see any code containing a catch block to recover from an
OutOfMemoryException. In fact, I’ve even had some developers tell me that the CLR doesn’t
let a program catch an OutOfMemoryException. For the record, this is absolutely not true;
you can catch this exception. In fact, there are many errors that are possible when executing
managed code and I hardly ever see developers write code that attempts to recover from
these potential failures.

Why .net exception is not caught?

It is because you have Code Contracts Runtime Contract Checking enabled in your project properties you use Release configuration. And if you are, your SafeMethodWillNeverThrow() method gets converted to the following with the help of Code Contracts rewriter:

public static void SafeMethodWillNeverThrow()
{
object something = ThrowsNewException();
try
{
Func<int, string> func1 = p => something.ToString();
}
catch (Exception)
{
}
}

Ouch!

Conclusion: Do not trust in what you see - read IL :).

The issue is reproducible with following Code Contracts versions:

  1. 1.4.50327.0

  2. 1.4.50126.1

    I am using Code Contracts and would like to have the error fixed ASAP.
    I have posted it to Code Contracts forum. The only way to have it fixed soon is to attract enough attention to it. So please vote up, especially on the Code Contracts forum

Update May 2016:

Version 1.9.10714.2 gives a different exception
Unhandled Exception: System.InvalidProgramException: Common Language Runtime detected an invalid program.

How do you judge whether to make an exception checked or unchecked?

The meaning of the quote is this: If the client code can not recover from the problem, it needs to let the exception propagate to higher layers. If you use checked exceptions for that, you need to declare the checked exception through all call layers without benefit.

To rephrase the quote: If the exception is expected to propagate through the layers, make it unchecked. Only make it checked if the caller can actually do something about it.

Trying to understand exceptions in C#

You should catch exceptions when you can handle the condition and do something useful. Otherwise you should let it bubble up the call stack and perhaps someone above you can handle it. Some apps have unhandled exception handlers to handle it at the outer most layer but in general, unless you know you have some useful way to handle it, let it go.

In your case, you're handling not being able to read a resource and informing the user. You're handling it. Concerning the generic exception, one thing you can do is catch and re-throw a better exception. If you do that, make sure you incude the root cause exception as the inner exception. You can also trace or log the details if appropriate.

throw new MyGoodExceptionType ("Could not read file", e);  // e is caught inner root cause.

Now the UI shows a good error and perhaps the inner root cause is in a log etc...

Some typical mistakes:

  • Handling exceptions deep in the stack in a generic library method: Remember that a common library function may get called in many different code paths. You likely don't have the context whether it should be handled and whether it's appropriate to handle it. the caller higher in the stack likely has context and knows whether it's safe to handle. Typically that means higher layers of code decide to handle. In lower layers, typically you let them flow.

  • Swallowing Exception: Some code catches exceptions (especially lower in the stack) and then the root condition just evaporates making it maddening to debug. Once agan, if you can handle it, do so. If not, let it go.

  • Exceptions should be exceptional: Don't use excpetions for flow control. For example, if you're reading a resource, don't try and read and then catch the exception and make a decision point. Instead, call ifexists, check bool and make decisions in your code. this especially helps when you set the debugger to break on exceptions. You should be able to run clean and if the debugger breaks, it should be a real issue. Having the debugger break constantly when debugging is problematic. I personally like throwing exceptions very rarely and always try to avoid for flow control.

Hope that helps.

C# explicitly defining what exceptions are thrown

There is nothing equivalent in C#: The Trouble with Checked Exceptions

Other than documentation, there is no way to declare an interface to say "methodX() should throw this exception on error".



Related Topics



Leave a reply



Submit