C#: Do we need checked exception in C#


We recently got hit by a bug where some method threw an exception which it was not supposed to. Since the thrown exception was not in the methods documented list of exception classes we did not have a catch for it and landed up with an unhandled exception crash. These kind of things are really bad when they originate from WinForm event handlers as there is no catch all block for every event and uncaught exceptions just terminate the form. 


My instant reaction was this wouldn’t have happened if we had checked exceptions  in C#. However, there has been a lot of debate on the inclusion of checked exception (as in Java) into C#. Ander’s Hejlsberg has a great rational on this topic here. I think we need a good solution with this exception business, Java’s solution is not good enough and C++ throw list is simply crap.


Checked Exceptions as in Java


<All Java code in this blog was written and tested with VJ# >


Checked exceptions mean that every method is supposed to declare the various exceptions it can throw in the method’s signature. The compiler then proceeds with static analysis to ensure that the method throws only those exceptions that it had declared or exceptions derived from them.

public class A extends Exception

{

}

public class B extends Exception

{

}

public class C extends B

{

}

public class Program

{

public static void func() throws B

{

throw new A(); // compilation failure

throw new B(); // OK

throw new C(); // OK as C extends B

}

}


In the Java code above the compilation fails when we try to throw A as it does not derive from B. The compiler not only verifies that the method throws only the correct exceptions it also verifies that the caller handles all those exceptions. By “handle” the caller either needs to catch these exceptions or include them in its throws list.

public class B extends Exception

{

}

public class C extends B

{

}

public static void func() throws B

{

throw new C();

}


For the above code you have two options of calling func

public static void foo()

{

try {

func();

}

catch (B b) {

// …

}

}


or

public static void foo() throws B

{

func();

}


In a micro sample like the one above checked exceptions looks super cool. So there is no need for documentation of list of exceptions. The compiler ensures that a method does not do anything sneaky and throw an exception it was not supposed to and it also ensures that you take care of all exceptions and do not become the author of a culprit method.


However, in large real-life projects the whole idea starts breaking down. For an excellent discussion on this read Hejlsberg’s comment


C++ throw list (Exception specification)


I cannot stop myself from stating that this is one of the most crappiest feature (??) in C++. First lets see how it works

int foo() throw (B)

{

throw new A();

}

int bar() throw ()

{

throw new A();

}


as in Java you can give a list of exceptions that the class can throw. If the list is empty then the method is not supposed to throw any exception. The problem is that this is totally misleading to most programmers and makes them believe that this list is enforced as in Java. The truth is that it isn’t. So the above code will compile just fine. The fact that foo is throwing A when its supposed to throw B and that bar is throwing A when its not supposed to throw any, is not checked by the compiler. This is more of exception specification (read fancy compiler supported documentation).


What the compiler does is that when an exception is thrown which does not match the specification the global unexpected() handler is called at runtime. Since rarely you can do something intelligent in the global handler, you’d need to live with the terminate() call from there and watch in horror as your program dies miserably. The whole of this happens at run-time and there is no static check.


So simply put the general guidelines is almost always “do not use exception specification”. Sometimes however, the empty throw() is allowed as this can help the compiler optimize generated code as it need not take care of all the stack unwinding stuff. However, if you do get an exception in code you’ve marked with throw(), just pray and hope that the comp just does’t burn itself down….


Microsoft Visual C++ compiler does the right thing of just parsing and ignoring the throw list (exception specification). I think the time spent on implementing the C++ spec on this would’ve been waste of time and no-value would ‘ve been added.


C# and Spec#


C# wisely (IMO) does not include checked exception. However, Spec# from Microsoft Research does implement this. Read about spec# implementation here. Spec# follows Java is its implementation and it used data-flow rules like the ones used in definite assignment to verify this.


Since C# picks up a lot of things from Spec# (and COmega) I expected this to move into C#. Atleast for C#3.0 the announced plans do not include checked exceptions in C#….

Comments (11)

  1. I have no argument about checked exceptions; I think they get in the way more than they help.

    However, terminating a form on an unchecked exception is probably going to cause more problems than it fixes. Sure there’s always the odd case where the exception will be thrown repeatedly and the user can’t close the window themselves but more often than not it’s a single exception as a result of something the user did. Allowing the form to stay open and degrade gracefully is a better solution from the point of view of the user. Perhaps they can manage to save their work in some way instead of rudely shutting down.

  2. Keith J. Farmer says:

    To gracefully terminate, you must be aware of the exception.

    There are two things with checked exceptions — one is notification by the compiler. That is valuable. The other is simply whether the compiler considers an uncaught exception to be a compilation error or merely a warning.

    So add checked exceptions. Add them in such a way that we can see the distinct types of exceptions that can result from each method call (or, as IDE candy, highlight a block and learn the distinct exceptions). But don’t make them compilation errors — not yet.

    There’s an obvious need to alert developers of exceptions they may not know about, and the compiler can manage that without hindering progress.

  3. matt says:

    If you add checked exceptions to C# I’ll tear my eyes out and jump off a cliff. I’m not kidding. I really mean it!

    Save a life… say "No" to checked exceptions in C#.

  4. Checked exceptions are absolutely essential to robust programming. If you are not doing robust programming, then you are an idiot. When you read a file, there are simply things you need to check for such as that the file exists. Without checked exceptions, you miss doing this. What if you do remember this, what if you forget to check for the Permissions Exception where the file exists but you can’t read it. There are so many .Net programs that are not robust because these things are not being checked. The only reason not to have them is to be a lazy developer. There are, of course, things you can’t do anything about such as division by zero or index out of bounds exceptions that indicate programming flaws instead of external conditions that can be handled and Java does not make them checked exceptions.

  5. Anders Dalvander says:

    Anson Horton describes "Why doesn’t C# have exception specifications?" in this article: http://msdn.microsoft.com/vcsharp/programming/language/ask/exceptionspecs/default.aspx

  6. X.Static says:

    @Brant

    Did you actually read the Hejlsberg interview? Checked exceptions (the Java way at least) are great in theory, but out in the real world they’re actually rarely used due to the exact factors that Anders states in the interview. Most of the Java guys I know don’t use them.

  7. Jonesie says:

    The lack of checked exceptions are often touted by Java people as justification for calling C# inferior – while they blindly overlook all the advantages of C#.

    It is very easy (and well documented) to create a global exception handler in WinForms applications. Checkout the event handler Application.ThreadException.

  8. "It is very easy (and well documented) to create a global exception handler in WinForms applications. Checkout the event handler Application.ThreadException."

    Likewise it would have been just as easy for the default to be to keep the application up and make the programmer add said event handler if they wanted to terminate their application forcefully. Defaults are supposed to be defaults because they are the most common option.

  9. Kristoffer, I missed that one about the global exception handler. My friend Amit here in IDC pointed out that to me, but I guess I was sloppy and did not add that or I think Amit was sloppy and did not add it as a comment (I know he reads the blog 🙂 )

    Global exception handlers are almost never good idea and you can do very little there. Very soon you’d need to add those ugly state information to figure out what caused you to reach there and whether you can actually recover. So you’d need a special handler for out-of-memory exception where almost certainly you are out of luck, or what about the stack overflow exception of the divide by zero error. The list is endless. When you just think you’ve figured out you’d be hit by another one. Trust me on this, I have tried doing this once. Though theoretically its possible to do, it soon becomes humanly impossible to manage every unhandled exception from a considerable sized project in a single handler.

  10. Lasse Vågsæther Karlsen says:

    I think the biggest problem I saw with checked exceptions had to do with inheritance.

    Say you have this:

    public class Storage

    {

    public Storage(…) { … }

    public virtual void Open() throws AccessDeniedException;



    }

    public class FileStorage

    {

    public FileStorage(String filename) : base() { … }

    public override void Open() … ()



    }

    Where I marked with (), what would you put here? Certainly opening a file would be able to throw a lot more exceptions than the base method would. Do you then go back and retrofit the base class with all the exception types all the inherited classes can throw? That might be a doable solution if you’re in control of the entire code base that this class is used in, but if that class is a class in a class library then no application using it would be able to add meaningful overrides as they would be limited in the types of exceptions they can throw.

    This might look similar to the versioning issue that Anders brought up in the article but breaking changes when introducing a new version is just that, breaking changes, and I do expect some changes when I upgrade a class library.

    In this case, however, I would think of checked exceptions as a really big limitation in the way I could use that class.

    I still think the best way to solve the problem of not having checked exceptions or any compiler-way of managing this is by documenting the class. Sure, you’ll find the odd method or class that throws an exception it is not supposed to (according to documentation).

    Then again, documentation is like software, it can have bugs too.

  11. abas says:

    how to create Event for a object at runtime