Using Exception Handling |
|
Techniques of Using Exceptions |
Introduction |
As mentioned in the previous lesson, the Exception class is equipped with a Message property that holds a string about the error that occurred. The message of this property may not be particularly useful to a user. Fortunately, you can create your own message and pass it to the Exception class. To be able to receive custom messages, the Exception class provides the following constructor: public Exception(string message); Besides using this class or one of its derived classes in a catch clause, you can call this constructor to give a new and customized implementation of the exception. |
The calculator simulator we have studied so far performs a division as one of its assignments. We learned that, in order to perform any operation, the compiler must first make sure that the user has entered a valid operator. Provided the operator is one of those we are expecting, we also must make sure that the user typed valid numbers. Even if these two criteria are met, it was possible that the user enter 0 for the denominator. The block that is used to check for a non-zero denominator depends on the exception that validates the operators. The exception that could result from a zero denominator depends on the user first entering a valid number for the denominator. You can create an exception inside of another. This is referred to as nesting an exception. This is done by applying the same techniques we used to nest conditional statements. This means that you can write an exception that depends on, or is subject to, another exception. To nest an exception, write a try block in the body of the parent exception. The nested try block must be followed by its own catch(es) clause. To effectively handle the exception, make sure you include an appropriate throw in the try block. Here is an example: using System; class Program { static int Main() { double Operand1, Operand2; double Result = 0.00; char Operator; Console.WriteLine( "This program allows you to perform an operation on two numbers"); try { Console.Write("Enter a number: "); Operand1 = double.Parse(Console.ReadLine()); Console.Write("Enter an operator: "); Operator = char.Parse(Console.ReadLine()); Console.Write("Enter a number: "); Operand2 = double.Parse(Console.ReadLine()); if (Operator != '+' && Operator != '-' && Operator != '*' && Operator != '/') throw new Exception(Operator.ToString()); switch (Operator) { case '+': Result = Operand1 + Operand2; Console.WriteLine("\n{0} + {1} = {2}", Operand1, Operand2, Result); break; case '-': Result = Operand1 - Operand2; Console.WriteLine("\n{0} - {1} = {2}", Operand1, Operand2, Result); break; case '*': Result = Operand1 * Operand2; Console.WriteLine("\n{0} * {1} = {2}", Operand1, Operand2, Result); break; case '/': // The following exception is nested in the previous try try { if (Operand2 == 0) throw new DivideByZeroException("Division by zero is not allowed"); Result = Operand1 / Operand2; Console.WriteLine("\n{0} / {1} = {2}", Operand1, Operand2, Result); } catch (DivideByZeroException ex) { Console.WriteLine(ex.Message); } break; } } catch (Exception ex) { Console.WriteLine("\nOperation Error: {0} is not a valid operator", ex.Message); } return 0; } } Here is an example of running the program: This program allows you to perform an operation on two numbers Enter a number: 324.53 Enter an operator: / Enter a number: 0 Division by zero is not allowed Press any key to continue . . .
One of the most effective techniques used to deal with code is to isolate assignments. We learned this when studying methods of classes. For example, the switch statement that was performing the operations in the “normal” version of our program can be written as follows: using System; class Program { static int Main() { double Number1, Number2; double Result = 0.00; char Operator; Console.WriteLine( "This program allows you to perform an operation on two numbers"); try { Console.WriteLine("To proceed, enter"); Console.Write("First Number: "); Number1 = double.Parse(Console.ReadLine()); Console.Write("An Operator (+, -, * or /): "); Operator = char.Parse(Console.ReadLine()); if (Operator != '+' && Operator != '-' && Operator != '*' && Operator != '/') throw new Exception(Operator.ToString()); Console.Write("Second Number: "); Number2 = double.Parse(Console.ReadLine()); if (Operator == '/') if (Number2 == 0) throw new DivideByZeroException("Division by zero is not allowed"); Result = Calculator(Number1, Number2, Operator); Console.WriteLine("\n{0} {1} {2} = {3}", Number1, Operator, Number2, Result); } catch (FormatException) { Console.WriteLine("The number you typed is not valid"); } catch (DivideByZeroException ex) { Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine( "\nOperation Error: {0} is not a valid operator", ex.Message); } return 0; } static double Calculator(double Value1, double Value2, char Symbol) { double Result = 0.00; switch (Symbol) { case '+': Result = Value1 + Value2; break; case '-': Result = Value1 - Value2; break; case '*': Result = Value1 * Value2; break; case '/': Result = Value1 / Value2; break; } return Result; } } Here is one example of running the program: This program allows you to perform an operation on two numbers To proceed, enter First Number: 248.84 An Operator (+, -, * or /): * Second Number: 57.93 248.84 * 57.93 = 14415.3012 Press any key to continue . . . Here is another example of running the program: This program allows you to perform an operation on two numbers To proceed, enter First Number: 12.55 An Operator (+, -, * or /): [ Operation Error: [ is not a valid operator Press any key to continue . . . You can still use regular methods along with methods that handle exceptions. As done in Main(), any method of a program can take care of its own exceptions that would occur in its body. Here is an example of an exception handled in a method: using System; class Program { static int Main() { double Number1, Number2; double Result = 0.00; char Operator; Console.WriteLine( "This program allows you to perform an operation on two numbers"); try { Console.WriteLine("To proceed, enter"); Console.Write("First Number: "); Number1 = double.Parse(Console.ReadLine()); Console.Write("An Operator (+, -, * or /): "); Operator = char.Parse(Console.ReadLine()); if (Operator != '+' && Operator != '-' && Operator != '*' && Operator != '/') throw new Exception(Operator.ToString()); Console.Write("Second Number: "); Number2 = double.Parse(Console.ReadLine()); Result = Calculator(Number1, Number2, Operator); } catch (FormatException) { Console.WriteLine("The number you typed is not valid"); } catch (Exception ex) { Console.WriteLine( "\nOperation Error: {0} is not a valid operator", ex.Message); } return 0; } static double Calculator(double Value1, double Value2, char Symbol) { double Result = 0.00; switch (Symbol) { case '+': Result = Value1 + Value2; Console.WriteLine("\n{0} + {1} = {2}", Value1, Value2, Result); break; case '-': Result = Value1 - Value2; Console.WriteLine("\n{0} - {1} = {2}", Value1, Value2, Result); break; case '*': Result = Value1 * Value2; Console.WriteLine("\n{0} * {1} = {2}", Value1, Value2, Result); break; case '/': // The following exception is nested in the previous try try { if (Value2 == 0) throw new DivideByZeroException("Division by zero is not allowed"); Result = Value1 / Value2; Console.WriteLine("\n{0} / {1} = {2}", Value1, Value2, Result); } catch (DivideByZeroException ex) { Console.WriteLine(ex.Message); } break; } return Result; } } Isolating assignments and handing them to method is an important matter in the area of application programming. Consider a program that handles a simple exception such as this one: using System; class Program { static int Main() { double Number1, Number2; double Result = 0.00; char Operator = '/'; Console.WriteLine("This program allows you to perform a division of two numbers"); try { Console.Write("Enter a number: "); Number1 = double.Parse(Console.ReadLine()); Console.Write("Enter a number: "); Number2 = double.Parse(Console.ReadLine()); if (Number2 == 0) throw new DivideByZeroException("Division by zero is not allowed"); Result = Number1 / Number2; Console.WriteLine("\n{0} / {1} = {2}", Number1, Number2, Result); } catch (DivideByZeroException ex) { Console.WriteLine(ex.Message); } return 0; } } One of the ways you can use methods in exception routines is to have a central method that receives variables, and sends them to other external methods. The external method tests the value of a variable. If an exception occurs, the external method displays or sends a throw. This throw can be picked up by the method that sent the error. Observe the following example that implements this scenario: using System; class Program { static int Main() { double Number1, Number2; Console.WriteLine("This program allows you to perform a division of two numbers"); try { Console.Write("Enter a number: "); Number1 = double.Parse(Console.ReadLine()); Console.Write("Enter a number: "); Number2 = double.Parse(Console.ReadLine()); Division(Number1, Number2); } catch(DivideByZeroException ex) { Console.WriteLine(ex.Message); } return 0; } static void Division(double a, double b) { double Result; // If an exception occurred, if( b == 0 ) // then throw a string to the function caller throw new DivideByZeroException("Division by zero is not allowed"); Result = a / b; Console.WriteLine("\n{0} / {1} = {2}", a, b, Result); } } In this program, the Division method receives two values that it is asked to perform a division with. The Division method analyzes the second argument that represents the denominator. If this argument is zero, an exception is found and the Division method throws a DivideByZeroException exception. A method can also be called to perform more than one test to eventually throw more than one exception. Such a method can (and should) be programmed to throw different types of exceptions.
As seen in the previous lesson and in the above sections, exception handling is a great part of the .NET Framework. As high as it is supported by various classes of the .NET, it is possible that you want to further customize the handling of exceptions in your application. One way you can do this is to create your own exception class.
The Exception class of the .NET Framework is a great tool for handling exceptions in a C# application. To deal with particular errors, various classes are derived from Exception. If for some reason the Exception class and none of the Exception-based classes fulfills your requirement, you can derive a new class from Exception or from one of the available Exception-based classes. To derive a class from Exception or from one of its classes, simply follow the rules we reviewed from class inheritance. Here is an example of a class based on Exception: public class CustomException : Exception { } There is no real rule to follow as to what class to derive from but it may be a good idea to derive your class from one that already addresses your issue but not the way you want. For example, if you want to create a class that would process numeric values but you think the FormatException class is not doing what you want, you can derive your class from FormatException. After deriving the class, you can add the necessary members as you see fit. Remember that the primary characteristic of an exception is to present a message to the user. In Exception-based classes, this message is represented by the Message property. Therefore, if you want to prepare a custom message for your class, you can override or new this property. Here is an example: public class IntegerException : Exception { public override string Message { get { return "The value you entered is not a valid integer"; } } } Once you have created and customized your exceptional class, you can use it the same way you would another exception class, such as throwing it. Here is an example using System; public class DigitException : Exception { private char c; public DigitException(char x) { c = x; } public override string Message { get { return "The character you entered is not a valid digit"; } } } class Program { static int Main() { try { char chNumber = '0'; Console.Write("Enter a digit (0 to 9): "); chNumber = char.Parse(Console.ReadLine()); if ((chNumber != '0') && (chNumber != '1') && (chNumber != '2') && (chNumber != '3') && (chNumber != '4') && (chNumber != '5') && (chNumber != '6') && (chNumber != '7') && (chNumber != '8') && (chNumber != '9')) throw new DigitException(chNumber); Console.WriteLine("Number: {0}\n", chNumber); } catch (DigitException ex) { Console.WriteLine(ex.Message); } catch (FormatException ex) { Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine(ex.Message); } return 0; } } Here is an example of running the program: Enter a digit (0 to 9): 8 Number: 8 Press any key to continue . . . Here is another example of running the program: Enter a digit (0 to 9): w The character you entered is not a valid digit Press any key to continue . . .
|
|
||
Previous | Copyright © 2008-2016, FunctionX, Inc. | Next |
|