Chapter 9
Exception Handling

Kurt Nørmark ©
Department of Computer Science, Aalborg University, Denmark


Abstract
Previous lecture Next lecture
Index References Contents
In object-oriented programming languages errors can be represented as objects. Run-time errors are referred to as exceptions. In this section we will study how exceptions can be represented as objects, and how errors can be classified by means class hierarchies. In addition, we will take a look at the facilities in C# that allows us to throw and handle the exceptions.


Fundamental Questions about Exception Handling

What is the motivation?
Slide Annotated slide Contents Index
References Textbook 

Why should we care about errors and error handling?

  • Understand the nature of errors

    • "An error is not just an error"

  • Prevent as many errors as possible in the final program

    • Automatically - via tools

    • Manually - in a distinguished testing effort

  • Make programs more robust

    • A program should, while executing, be able to resist and survive unexpected situations

What is an error?
Slide Annotated slide Contents Index
References Textbook 

The word "error" is often used in an undifferentiated way

  • Errors in the design/implementation process

    • Due to a wrong decision at an early point in time - a mental flaw

  • Errors in the source program

    • Illegal use of the programming language

    • Erroneous implementation of an algorithm

  • Errors in the program execution - run time errors

    • Exceptions - followed by potential handling of the exceptions

Errors in the development process may lead to errors in the source program.

Errors in the source program may lead to errors in the running program

What is normal? What is exceptional?
Slide Annotated slide Contents Index
References Textbook 

It is useful to draw the border between normal program aspects and exceptional program aspects

  • Normal program aspects

    • Situations anticipated and dealt with in the conventional program flow

    • Programmed with use of selective and iterative control structures

  • Exceptional program aspects

    • Situations anticipated, but not dealt with "in normal ways" by the programmer

      • Leads to an exception

      • Recoverable via exception handling. Or non-recoverable

    • Situations not anticipated by the programmer

      • Leads to an exception

      • Recoverable via exception handling. Or non-recoverable

    • Problems beyond the control of the program

Examples of normal and exceptional aspects
Slide Annotated slide Contents Index
References 

Normal aspects and exceptional aspects - anticipated or non-anticipated

Program: A recursive Factorial function.
  public static long Factorial(int n){
    if (n == 0)
      return 1;
    else return n * Factorial(n - 1);
  }

1.   Negative input

2.   Wrong type of input

3.   Wrong type of multiplication

4.   Numeric overflow

5.   Out of memory

6.   Loss of power

7.   Machine failure

8.   Sun failure

Program: An iterative Factorial function.
  public static BigInteger Factorial(int n){
    if (n >= 0){
      BigInteger res = 1;
      for(int i = 1; i <= n; i++)
        res = res * i;
      return res;
    }
    else throw new ArgumentException("n must be non-negative");
  }  

Program: An iterative Factorial function with a precondition - not C# 3.0.
  public static BigInteger Factorial(int n){
    require n >= 0;                                 
    BigInteger res = 1;                             
    for(int i = 1; i <= n; i++)                     
      res = res * i;
    return res;
    ensure res = n * n-1 * ... * 1;  
  }  

When are errors detected?
Slide Annotated slide Contents Index
References Textbook 

It is attractive to find errors as early as possible

  • During design and programming - Go for it.

  • During compilation - syntax errors or type errors - Attractive.

  • During testing - A lot of hard work. But necessary.

  • During execution and final use of the program

    • Handled errors - OK. But difficult.

    • Unhandled errors - A lot of frustration.

Exception handling is primarily concerned with detection and handling of "the real exceptions" in the executing program

Exception handling adds robustness to the final program

How are errors handled?
Slide Annotated slide Contents Index
References Textbook 

How should a run-time error be handled?

  • Ignore

    • False alarm - Naive

  • Report

    • Write a message on the screen or in a log - Helpful for subsequent correction of the source program

  • Terminate

    • Stop the program execution in a controlled an gentle way - Save data, close connections

  • Repair

    • Recover from the error in the running program - Continue normal program execution when the problem is solved

Where are errors handled?
Slide Annotated slide Contents Index
References Textbook 

Should an error be handled locally, or at another place in the program?

  • Handle errors at the place in the program where they occur

    • If possible, this is the easiest approach

    • Not always possible nor appropriate

  • Handle errors at another place

    • Along the calling chain

    • Separation of concerns


Conventional Exception Handling

Exception Handling Approaches
Slide Annotated slide Contents Index
References Textbook 

  • Printing error messages

    • Console.Out.WriteLine(...)   or   Console.Error.WriteLine(...)

    • Error messages on standard output are - in general - a bad idea

Reference

  • Returning error codes

    • Like in many C programs

    • In conflict with a functional programming style, where we need to return data

  • Set global error status variables

    • Almost never attractive

  • Raise and handle exceptions

    • A special language mechanism to raise an error

    • Rules for propagation of errors

    • Special language mechanisms for handling of errors

Mixing normal and exceptional cases
Slide Annotated slide Contents Index
References Textbook 

Arbitrary mixing of normal and exceptional program aspects can be very confusing

Program: A file copy program.
using System;
using System.IO;

public class CopyApp {

  public static void Main(string[] args) {
    FileInfo   inFile  = new FileInfo(args[0]),
               outFile = new FileInfo(args[1]);
    FileStream inStr   = inFile.OpenRead(),     
               outStr  = outFile.OpenWrite();   
    int c;
   do{                                          
      c = inStr.ReadByte();                     
      if(c != -1) outStr.WriteByte((byte)c);
   } while (c != -1);  

   inStr.Close();                               
   outStr.Close();
 }
}

Program: A file copy program with excessive error handling.
using System;
using System.IO;

public class CopyApp {                              

  public static void Main(string[] args) {
    FileInfo inFile;
    do {                                            
        inFile = new FileInfo(args[0]);             
        if (!inFile.Exists)                         
          args[0] = "some other input file name";
    } while (!inFile.Exists);

    FileInfo outFile;
    do {                                               
        outFile = new FileInfo(args[1]);               
        if (outFile.Exists)                            
          args[1] = "some other output file name";
    } while (outFile.Exists);

    FileStream inStr   = inFile.OpenRead(),
               outStr  = outFile.OpenWrite();
    int c;
    do{
       c = inStr.ReadByte();
       if(c != -1) outStr.WriteByte((byte)c);
       if (StreamFull(outStr))                              
         DreamCommand("Fix some extra room on the disk");   
    } while (c != -1);  

    inStr.Close();
    if (!FileClosed(inStr))                                            
      DreamCommand("Deal with input file which cannot be closed");     

    outStr.Close();                                                    
    if (!FileClosed(outStr))                                           
      DreamCommand("Deal with output file which cannot be closed");
  }



  /* Programming pseudo commands for the sake of this example */

  public static void DreamCommand(string str){
    // Carry out the command str
  }

  public static bool FileClosed(Stream str){
    // Return if the stream str is closed
  }

  public static bool StreamFull(Stream str){
    // Return if the stream str is full
  }    

}

The normal program almost disappears in the error handling code


Object-oriented Exception Handling

Errors as Objects
Slide Annotated slide Contents Index
References Textbook 

All relevant knowledge about an error is encapsulated in an object

  • Encapsulation of relevant error knowledge

    • Place of occurrence (class, method, line number)

    • Kind of error

    • Error message formulation

    • Call stack information

  • Transportation of the error

    • From the place of origin to the place of handling

    • Via a special throw mechanism in the language

Classification of Errors
Slide Annotated slide Contents Index
References Textbook 

Errors can be classified and specialized by means of a class hierarchy

A sample error classification hierarchy


Exceptions and Exception Handling in C#

Exceptions in a C# program
Slide Annotated slide Contents Index
References Textbook 

A C# program with an exception

Program: A C# program with an exception.
using System;

class ExceptionDemo{

  public static void Main(){
    int[] table = new int[6]{10,11,12,13,14,15};
    int idx = 6;                                   
                                                   
    M(table, idx);
  }

  public static void M(int[] table, int idx){
    Console.WriteLine("Accessing element {0}: {1}", 
                       idx, table[idx]);           
  }

}

Program: Output from the C# program with an exception.
Unhandled Exception: System.IndexOutOfRangeException: 
 Index was outside the bounds of the array.
     at ExceptionDemo.M(Int32[] table, Int32 idx)
     at ExceptionDemo.Main()

The program stops executing when a run-time error is encountered

The try-catch statement C#
Slide Annotated slide Contents Index
References Textbook 

The try-catch statement allows us handle certain exceptions instead of stopping the program

Syntax: The syntax of the try-catch statement C#

try
  try-block
catch (exception-type-1 name)
  catch-block-1
catch (exception-type-2 name)
  catch-block-2
...

  • Program fragments that may lead to potential exceptions

    • In try-block

  • Program fragments that may handle the exceptions

    • In catch-block-1, catch-block-2, ...

Handling exceptions in C#
Slide Annotated slide Contents Index
References Textbook 

A C# program with a handled exception

Program: A C# program with a handled exception.
using System;

class ExceptionDemo{

  public static void Main(){
    int[] table = new int[6]{10,11,12,13,14,15};
    int idx = 6;

    M(table, idx);
  }

  public static void M(int[] table, int idx){
    try{                                                       
      Console.WriteLine("Accessing element {0}: {1}", 
                         idx, table[idx]);
      Console.WriteLine("Accessing element {0}: {1}", 
                         idx-1, table[idx-1]);
    } 
    catch (IndexOutOfRangeException e){                        
      int newIdx = AdjustIndex(idx,0,5);                       
      Console.WriteLine("We get element number {0}: {1}",      
                         newIdx, table[newIdx]);            
    }   
    Console.WriteLine("End of M");   
  }



  public static int AdjustIndex(int i, int low, int high){     
    int res;                                                   
    if (i < low)
      res = low;
    else if (i > high)
      res = high;
    else res = i;

    return res;
  }
}

Program: Output from the C# program with a handled exception.
We get element number 5: 15
End of M

Exercise 9.2. Exceptions in Convert.ToDouble

The static methods in the static class System.Convert are able to convert values of one type to values of another type.

Consult the documentation of System.Convert.ToDouble. There are several overloads of this method. Which exceptions can occur by converting a string to a double?

Write a program which triggers these exceptions.

Finally, supply handlers of the exceptions. The handlers should report the problem on standard output, rethrow the exception, and then continue.

The program handles the exception and brings the program execution back on track

The hierarchy of exceptions in C#
Slide Annotated slide Contents Index
References Textbook 

An excerpt of the exception class hierarchy of C#

References

  • Exception

    • ApplicationException

      • Your own exception types

    • SystemException

      • ArgumentException

        • ArgumentNullException

        • ArgumentOutOfRangeException

      • DivideByZeroException

      • IndexOutOfRangeException

      • NullReferenceException

      • RankException

      • StackOverflowException

      • IOException

        • EndOfStreamException

        • FileNotFoundException

        • FileLoadException

Exercise 9.4. Exceptions in class Stack

In the lecture about inheritance we specialized the abstract class Stack.

Now introduce exception handling in your non-abstract specialization of Stack. I suggest that you refine your own solution to the previous exercise. It is also possible to refine my solution.

More specifically, introduce one or more stack-related exception classes. The slide page "Raising and throwing exceptions in C#" tells you how to do it. Make sure to specialize the appropriate pre-existing exception class!

Arrange that Push on a full stack and that Pop/Top on an empty stack throw one of the new exceptions. Also, in the abstract stack class, make sure that ToggleTop throws an exception if the stack is empty, or if the stack only contains a single element.

Finally, in a sample client program such as this one, handle the exceptions that are thrown. In this exercises it is sufficient to report the errors on standard output.

Exercise 9.4. More exceptions in class Stack

In continuation of the previous exercise, we now wish to introduce the following somewhat unconventional handling of stack exceptions:

  • If you push an element on a full stack throw half of the elements away, and carry out the pushing.
  • If you pop/top an empty stack, push three dummy elements on the stack, and do the pop/top operation after this.

With these ideas, most stack programs will be able to terminate normally (run to the end).

I suggest that you introduce yet another specialization of the stack class, which specializes Push, Pop, and Top. The specialized stack operations should handle relevant stack-related exceptions, and delegate the real work to its superclass. Thus, in the specialized stack class, each stack operation, such as Push, you should embed base.push(el) in a try-catch control structure, which repairs the stack - as suggested above - in the catch clause.

The class System.Exception in C#
Slide Annotated slide Contents Index
References Textbook 

Some observations about the base class of all exceptions

  • Constructors

    • Parameterless: Exception()

    • With an explanation: Exception(string)

    • With an explanation and an inner exception: Exception(string,Exception)

  • Properties

    • Message: A description of the problem (string)

    • StackTrace: The call chain from the point of throwing to the point of catching

    • InnerException: The exception that caused the current exception

    • Data: A dictionary of key/value pairs.

      • For communication in between functions along the exception propagation chain.

    • Others...

Reference

Handling more than one type of exception in C#
Slide Annotated slide Contents Index
References Textbook 

Multiple types of exceptions can be handled in a single try control structure

Program: A C# program with an exception handling attempt - not a success.
using System;

class ExceptionDemo{

  public static void Main(){
    int[] table = new int[6]{10,11,12,13,14,15};
    int idx = 6;

    M(table, idx);
  }

  public static void M(int[] table, int idx){
    try{                                                     
      Console.WriteLine("Accessing element {0}: {1}", 
                         idx, table[idx]);
    } 
    catch (NullReferenceException){                          
      Console.WriteLine("A null reference exception");
      throw;      // rethrowing the exception
    }   
    catch (DivideByZeroException){                           
      Console.WriteLine("Divide by zero");
      throw;      // rethrowing the exception                
    }

  }
}

Program: Output from the C# program with an unhandled exception.
Unhandled Exception: 
 System.IndexOutOfRangeException:
  Index was outside the bounds of the array.
   at ExceptionDemo.M(Int32[] table, Int32 idx)
   at ExceptionDemo.Main()

Program: A C# program with an exception handling attempt - now successful.
using System;

class ExceptionDemo{

  public static void Main(){
    int[] table = new int[6]{10,11,12,13,14,15};
    int idx = 6;

    M(table, idx);
  }

  public static void M(int[] table, int idx){
    try{                                                      
      Console.WriteLine("Accessing element {0}: {1}", 
                         idx, table[idx]);
    } 
    catch (NullReferenceException){                           
      Console.WriteLine("A null reference exception");        
      throw;      // rethrowing the exception                 
    }  
    catch (DivideByZeroException){
      Console.WriteLine("Divide by zero");
      throw;      // rethrowing the exception
    } 
    catch (IndexOutOfRangeException){                         
      int newIdx = AdjustIndex(idx,0,5);                      
      Console.WriteLine("We get element number {0}: {1}", 
                         newIdx, table[newIdx]);            
    }   
    catch (Exception){                                        
      Console.WriteLine("We cannot deal with the problem");   
      throw;     // rethrowing the exception
    }

  }



  public static int AdjustIndex(int i, int low, int high){
    int res;
    if (i < low)
      res = low;
    else if (i > high)
      res = high;
    else res = i;

    return res;
  }
}

Program: Output from the C# program with a handled exception.
We get element number 5: 15

Handle specialized exceptions before general exceptions

Propagation of exceptions in C#
Slide Annotated slide Contents Index
References Textbook 

Unhandled exceptions are propagated along the call chain

Program: A C# program with simple propagation of exception handling.
using System;

class ExceptionDemo{

  public static void Main(){
    int[] table = new int[6]{10,11,12,13,14,15};
    int idx = 6;

    try{                                                     
      M(table, idx);                                         
    }   
    catch (IndexOutOfRangeException){                        
      int newIdx = AdjustIndex(idx,0,5);
      M(table, newIdx);                                      
    }
    Console.WriteLine("End of Main"); 
  }

  public static void M(int[] table, int idx){
    try{                                                    
      Console.WriteLine("Accessing element {0}: {1}",       
                         idx, table[idx]);                  
    }                                                       
    catch (NullReferenceException){
      Console.WriteLine("A null reference exception");
      throw;      // rethrowing the exception
    }   
    catch (DivideByZeroException){
      Console.WriteLine("Dividing by zero");
      throw;     // rethrowing the exception
    }

    Console.WriteLine("End of M"); 
  }



  public static int AdjustIndex(int i, int low, int high){  
    int res;
    if (i < low)
      res = low;
    else if (i > high)
      res = high;
    else res = i;

    return res;
  }
}

Program: Output from the C# program simple propagation.
Accessing element 5: 15
End of M
End of Main

Program: A C# program with deeper exception propagation chain.
using System;

class ExceptionDemo{

  public static void Main(){
    int[] table = new int[6]{10,11,12,13,14,15};
    int idx = 6;

    Console.WriteLine("Main");
    try{
      M(table, idx);                            
    }   
    catch (IndexOutOfRangeException){           
      M(table, AdjustIndex(idx,0,5));           
    }
  }

  public static void M(int[] table, int idx){
    Console.WriteLine("M(table,{0})", idx);
    N(table,idx);                               
  }

  public static void N(int[] table, int idx){
    Console.WriteLine("N(table,{0})", idx);
    P(table,idx);                                
  }

  public static void P(int[] table, int idx){            
    Console.WriteLine("P(table,{0})", idx);              
    Console.WriteLine("Accessing element {0}: {1}",      
                       idx, table[idx]);
  }



  public static int AdjustIndex(int i, int low, int high){   
    int res;
    if (i < low)
      res = low;
    else if (i > high)
      res = high;
    else res = i;

    return res;
  }
}

Program: Output from the C# program deeper exception propagation.
Main
M(table,6)
N(table,6)
P(table,6)
M(table,5)
N(table,5)
P(table,5)
Accessing element 5: 15

Exercise 9.5. Revealing the propagation of exceptions

We have written a program that reveals how exceptions are propagated. In the program output, we see that the calling chain is Main, M, N, P.

The program output does not, however, reveal that the chain is followed in reverse order in an attempt to find an appropriate exception handler.

Revise the program with handlers in M, N, and P that touch the exception without actually handling it. The handlers should reveal, on standard output, that P, N, and M are passed in an attempt to locate a relevant exception handler. Rethrow the exception in each case. See here how this can be done.

Raising and throwing exceptions in C#
Slide Annotated slide Contents Index
References Textbook 

We are using an athletic metaphor for establishing an error condition

Syntax: The syntax of exception throwing in C#

 throw exception-object

Program: A throw statement in C#.
...
throw new MyException("Description of problem");
...

Program: Definition of the exception class.
class MyException: ApplicationException{
  public MyException(String problem): 
    base(problem){
  }
}   

Try-catch with a finally clause
Slide Annotated slide Contents Index
References Textbook 

A finally part of a try statement ensures a given code block is executed both in case of success and failure of the try-block

Syntax: The syntax of the try-catch-finally statement C#

try
  try-block
catch (exception-type name)
  catch-block
...
finally
  finally-block

A try-finally control structure is sometimes used - without catch clauses - to ensure execution of the finally-block in cases the control leave the try-block abruptly

Program: Illustration of try-catch-finally.
using System;

class FinallyDemo{

  internal enum Control {Returning, Jumping, Continuing, Breaking,   
                         Throwing, Normal}                           

  public static void M(Control reason){
    for(int i = 1; i <= 1; i++)  // a single iteration               
      try{                                                           
        Console.WriteLine("\nEnter try: {0}", reason);
        if (reason == Control.Returning) return;
        else if (reason == Control.Jumping) goto finish;
        else if (reason == Control.Continuing) continue;
        else if (reason == Control.Breaking) break;
        else if (reason == Control.Throwing) throw new Exception();
        Console.WriteLine("Inside try");        
      }
      catch(Exception){                                              
        Console.WriteLine("Inside catch");                           
      }  
      finally{                                                       
        Console.WriteLine("Inside finally");                         
      }
    finish: return;
  }

  public static void Main(){
    for(int i = 0; i <= 5; i++)                                      
      M((Control)i);                                                 
  }
}

Program: Output from the try-catch-finally program.
Enter try: Returning
Inside finally

Enter try: Jumping
Inside finally

Enter try: Continuing
Inside finally

Enter try: Breaking
Inside finally

Enter try: Throwing
Inside catch
Inside finally

Enter try: Normal
Inside try
Inside finally

Rethrowing an exception
Slide Annotated slide Contents Index
References Textbook 

Inside a handler, you can either rethrow an exception or raise/throw a new exception

  • Rethrowing

    • Preserving information about the original exception, and the call chain

    • Usually recommended

Program: Rethrowing an exception.
using System;

class ExceptionDemo{    
                        
  public static void Main(){
    Console.WriteLine("Main");
    int[] table = new int[6]{10,11,12,13,14,15};
    int idx = 6;
    M(table, idx);      
  }

  public static void M(int[] table, int idx){
    Console.WriteLine("M(table,{0})", idx);   
    N(table,idx);
  }

  public static void N(int[] table, int idx){     
    Console.WriteLine("N(table,{0})", idx);       
    try{
      P(table,idx);                          
    }
    catch (IndexOutOfRangeException e){           
      // Will not/cannot handle exception here.   
      // Rethrow original exception.              
      throw;                                      
    }                                             
  }                                               

  public static void P(int[] table, int idx){
    Console.WriteLine("P(table,{0})", idx);
    Console.WriteLine("Accessing element {0}: {1}", 
                       idx, table[idx]);          
  }
}

Program: Output from the program that rethrows an exception.
Main
M(table,6)
N(table,6)
P(table,6)

Unhandled Exception: 
 System.IndexOutOfRangeException: 
  Index was outside the bounds of the array.
   at ExceptionDemo.P(Int32[] table, Int32 idx)
   at ExceptionDemo.N(Int32[] table, Int32 idx)
   at ExceptionDemo.M(Int32[] table, Int32 idx)
   at ExceptionDemo.Main()

Touching, but not handling the exception

An outer handler will see the original exception

Raising an exception in an exception handler
Slide Annotated slide Contents Index
References Textbook 

Inside a handler, you can either rethrow an exception or raise/throw a new exception

  • Raising and throwing a new exception

    • Use this approach if you, of some reason, want to hide the original exception

      • Security, simplicity, ...

    • Consider propagation of the inner exception

Program: Raising and throwing a new exception.
using System;

class ExceptionDemo{

  public static void Main(){                          
    int[] table = new int[6]{10,11,12,13,14,15};
    int idx = 6;
    M(table, idx);
  }

  public static void M(int[] table, int idx){         
    Console.WriteLine("M(table,{0})", idx);
    N(table,idx);
  }

  public static void N(int[] table, int idx){         
    Console.WriteLine("N(table,{0})", idx);           
    try{
      P(table,idx);
    }
    catch (IndexOutOfRangeException e){                               
      // Will not/can no handle here. Raise new exception.            
      throw new IndexOutOfRangeException("Index out of range");       
    }                                                                 
  }

  public static void P(int[] table, int idx){
    Console.WriteLine("P(table,{0})", idx);
    Console.WriteLine("Accessing element {0}: {1}", 
                       idx, table[idx]);                        
  }
}

Program: Output from the program that raises a new exception.
M(table,6)
N(table,6)
P(table,6)

Unhandled Exception: System.IndexOutOfRangeException: 
 Index out of range
   at ExceptionDemo.N(Int32[] table, Int32 idx)
   at ExceptionDemo.M(Int32[] table, Int32 idx)
   at ExceptionDemo.Main()

Program: Raising and throwing a new exception, propagating original inner exception.
using System;

class ExceptionDemo{

  public static void Main(){                            
    int[] table = new int[6]{10,11,12,13,14,15};
    int idx = 6;
    M(table, idx);
  }

  public static void M(int[] table, int idx){           
    Console.WriteLine("M(table,{0})", idx);
    N(table,idx);
  }

  public static void N(int[] table, int idx){           
    Console.WriteLine("N(table,{0})", idx);             
    try{
      P(table,idx);
    }
    catch (IndexOutOfRangeException e){                                      
      // Will not/cannot handle exception here.                              
      // Raise new exception with propagation of inner exception.            
      throw new IndexOutOfRangeException("Index out of range",  e);          
    }
  }

  public static void P(int[] table, int idx){
    Console.WriteLine("P(table,{0})", idx);
    Console.WriteLine("Accessing element {0}: {1}", 
                       idx, table[idx]);                                     
  }
}

Program: Output from the program that raises a new exception, with inner exception.
M(table,6)
N(table,6)
P(table,6)

Unhandled Exception: System.IndexOutOfRangeException: 
 Index out of range ---> System.IndexOutOfRangeException: 
  Index was outside the bounds of the array.
   at ExceptionDemo.P(Int32[] table, Int32 idx)
   at ExceptionDemo.N(Int32[] table, Int32 idx)
   --- End of inner exception stack trace ---
   at ExceptionDemo.N(Int32[] table, Int32 idx)
   at ExceptionDemo.M(Int32[] table, Int32 idx)
   at ExceptionDemo.Main()

Comparison with exception handling in Java
Slide Annotated slide Contents Index
References 

The catch or specify principle: A method either catches and handles an exception, or it specifies that it may throw the exception

  • In Java

    • the signatures of methods are extended with a throws clause

      • tells that the method may throw a given exceptions

    • a branch of the exception hierarchy - the so-called RuntimeExceptions - is exempted from the catch or specify principle

  • In C#

    • all exceptions correspond to Java RuntimeExceptions

Program: A Java program - does not compile. Main calls explosion without handling or specifying Problem.
// Java
class Problem extends Exception{
  Problem(){super();}
  Problem(String s) {super(s);}
}

public class CatchOrSpecifyDemo0 {

  public static void main(String[] args){   
      explosion();      // Compile-time error:
                        //   unreported exception Problem;
                        //   must be caught or declared to be thrown
  }

  static void explosion() throws Problem {    
    System.out.println("Explosion!");
    throw new Problem("We have an explosive problem");
  }

}

Program: A Java program - main handles Problem.
// Java
class Problem extends Exception{
  Problem(){super();}
  Problem(String s) {super(s);}
}

public class CatchOrSpecifyDemo1 {

  public static void main(String[] args){     
    try {
      explosion();
    }
    catch (Problem e) {
      System.out.println("We handled the problem!");
      System.out.println("Or did we?");
    }  // try
  }

  static void explosion() throws Problem{   
    System.out.println("Explosion!");
    throw new Problem("We have an explosive problem");
  }

}

Program: A Java program - main specifies Problem.
// Java
class Problem extends Exception{
  Problem(){super();}
  Problem(String s) {super(s);}
}

public class CatchOrSpecifyDemo2 {

  public static void main(String[] args) throws Problem  {   
      explosion();
  }

  static void explosion() throws Problem{                    
    System.out.println("Explosion!");
    throw new Problem("We have an explosive problem");
  }

}


Recommendations about exception handling

Recommendations about exception handling
Slide Annotated slide Contents Index
References Textbook 

  • Control flow

    • Do not use throw and try-catch as iterative or conditional control structures

    • Normal control flow should be done with normal control structures

  • Efficiency

    • It is time consuming to throw an exception

    • It is more efficient to deal with the problem as a normal program aspect - if possible

  • Naming

    • Suffix names of exception classes with "Exception"

  • Exception class hierarchy

    • Your own exception classes should be subclasses of ApplicationException

    • Or alternatively (as of a more recent recommendation) of Exception.

Reference

Recommendations about exception handling
Slide Annotated slide Contents Index
References Textbook 

  • Exception classes

    • Prefer predefined exception classes instead of programming your own exception classes

    • Consider specialization of existing and specific exception classes

  • Catching

    • Do not catch exceptions for which there is no cure

    • Leave such exceptions to earlier (outer) parts of the call-chain

  • Burying

    • Avoid empty handler exceptions - exception burrying

    • If you touch an exception without handling it, always rethrow it

Reference


Collected references
Contents Index
Use of the Console class for redirection of the error stream Later in these notes
Best practices for handling exceptions (MSDN)
Classification of errors Earlier in these notes
The class System.Exception MSDN2 API Documentation
The C# Exception class hierarchy Earlier in these notes

 

Chapter 9: Exception Handling
Course home     Author home     About producing this web     Previous lecture (top)     Next lecture (top)     Previous lecture (bund)     Next lecture (bund)     
Generated: February 7, 2011, 12:18:34