It's very useful to have C# halt execution when an exception occurs. When the code is halted while running with the IDE, you receive an error message and you're shown the offending line of code. However, when your project is run as a compiled program, unhandled exceptions will cause the program to terminate (crash to the desktop). This is one of the most undesirable things an application can do. Fortunately, you can prevent exceptions from stopping code execution (and terminating compiled programs) by writing code specifically designed to deal with exceptions. Exception-handling code is used to instruct C# on how to deal with an exception, rather than relying on C#'s default behavior.
Create a new Windows Application called Structured Error Handling. Change the name of the default form to flcsErrorHandlingExample, set its Text property to Try…Catch…Finally, and change the Main() entry point of the project to reference fclsErrorHandlingExample instead of Form1. Next, add a new button to the form and set its properties as follows:
Property | Value |
---|---|
Name | btnCatchException |
Location | 104,128 |
Size | 96,23 |
Text | Catch Exception |
Double-click the button and add the following code.
try { Debug.WriteLine("Try"); } catch { Debug.WriteLine("Catch"); } finally { Debug.WriteLine("Finally"); } Debug.WriteLine("Done Trying");
Remember to add using System.Diagnostics to the top of your class so that you can use the Debug.WriteLine() statement. |
As you can see, the try, catch, and finally statements use the braces ({ } ) to enclose statements. The try, catch, and finally structure is used to wrap code that may cause an exception; it provides the means of dealing with thrown exceptions. Table 16.2 explains the sections of this structure.
Three possible forms of try statements are the following:
This example is using a try block followed by a catch block, followed by a finally block. |
Press F5 to run the project and then click the button. Next, take a look at the contents of the Output window. The Output window should contain the following lines of text:
Try Finally
Done Trying
Here's what happened:
1. |
The try block begins, and code within the try section executes. |
2. |
No exception occurs, so code within the catch section doesn't execute. |
3. |
When all statements within the try section finish executing, the code within the finally section executes. |
4. |
When all statements within the finally section finish executing, execution jumps to the statement immediately following the try, catch, and finally statements. |
Stop the project now by choosing Stop Debugging from the Debug menu. Now that you understand the basic mechanics of the try, catch, and finally structure, you're going to add statements within the structure so that an exception occurs and gets handled.
Change the contents of the code to match this code:
long lngNumerator = 10; long lngDenominator = 0; long lngResult; try { Debug.WriteLine("Try"); lngResult = lngNumerator / lngDenominator; } catch { Debug.WriteLine("Catch"); } finally { Debug.WriteLine("Finally"); } Debug.WriteLine("Done Trying");
Again, press F5 to run the project; then click the button and take a look at the Output window. This time, the text in the Output window should read
Try Catch Finally
Done Trying
Notice that this time the code within the catch section is executed. This is because the statement that sets lngResult causes a DivideByZero exception. Had this statement not been placed within a catch block, C# would have raised the exception and an error dialog box would have appeared. However, because the statement is placed within the try block, the exception is “caught.” This means that when the exception occurred, C# directed execution to the catch section (you do not have to use a catch section, in which case caught exceptions are simply ignored). Notice also how the code within the finally section executed after the code within the catch section. Remember, code within the finally section always executes, regardless of whether an exception occurs.
Catching exceptions so that they don't crash your application is a noble thing to do, but it's only part of the error-handling process. Usually, you'll want to tell the user (in a friendly way) that an exception has occurred. You'll probably also want to tell the user what type of exception occurred. To do this, you have to have a way of knowing what exception was thrown. This is also important if you intend to write code to deal with specific exceptions. The catch statement enables you to specify a variable to hold a reference to an Exception object. Using this Exception object, you can get information about the exception. The following is the syntax used to place the exception in an Exception object:
catch ( Exception variablename)
Modify your catch section to match the following:
catch (Exception objException) { Debug.WriteLine("Catch"); MessageBox.Show("An error has occurred: " + objException.Message); }
The Message property of the Exception object contains the text that describes the specific exception that occurs. Run the project, click the Catch Exception button, and C# displays your custom error message (see Figure 16.7).
At times, you'll anticipate a specific exception being thrown. For example, you may write code that attempts to open a file when the file does not exist. In such an instance, you'll probably want the program to perform certain actions when this exception is thrown. When you anticipate a specific exception, you can create a catch section designed specifically to deal with that one exception.
Recall from the previous section that you can retrieve information about the current exception using a catch statement such as catch (Exception). By creating a generic Exception variable, this catch statement will catch any and all exceptions thrown by statements within the try section. To catch a specific exception, change the data type of the exception variable to a specific exception type. Remember the code you wrote earlier that caused a Format exception when an attempt was made to pass an empty string to the long.Parse() method? You could have used a try structure to deal with the exception, using code such as this:
long lngAnswer; try { lngAnswer = 100 / long.Parse(txtInput.Text); MessageBox.Show("100/" + txtInput.Text + " is " + lngAnswer); } catch (System.FormatException) { MessageBox.Show("You must enter a number in the text box."); } catch { MessageBox.Show("Caught an exception that wasn't a format exception."); }
Notice that two catch statements are in this structure. The first catch statement is designed to catch only a Format exception; it won't catch exceptions of any other type. The second catch statement doesn't care what type of exception is thrown; it catches all of them. This second catch statement acts as a “catch all” for any exceptions that aren't Format exceptions, because catch sections are evaluated from top to bottom, much like case statements in the switch structure. You could add more catch sections to catch other specific exceptions if the situation calls for it.
3.145.9.148