MCAD Exam 70-316: Handling Visual C# .NET Exceptions
Date: Jul 11, 2003
Terms you'll need to understand:
Exception
try block
catch block
finally block
throw statement
Validation
Validating event
ErrorProvider component
Techniques you'll need to master:
Know the default application behavior that occurs when an unhandled exception is encountered.
Understand the use of try, catch, and finally code blocks.
Understand the different techniques of user input validation.
This chapter discusses exceptions, which appear as an outcome of unexpected problems during the normal execution of a program. The chapter focuses on how to handle such exceptional situations with the help of try, catch, and finally blocks. You will also learn how to handle unhandled exceptions at the level of application domain.
We also discuss the different user input validation techniques and cover how to use the ErrorProvider component to display error messages.
Understanding Exceptions
When an application encounters an unexpected situation such as a missing file or input parameter, or a logical error such as performing a division by zero, the application generates exceptions. By default, when an exception is generated, the application terminates and generates an error display such as the one shown in Figure 3.1.
Figure 3.1 This is an example error message, caused when an application commits a logical error, such as attempting to divide by zero.
Unhandled exceptions in an application can result in unexpected termination and lost data, and potentially even can create security holes if input values are not properly restricted. Visual C# .NET helps you fire and handle exceptions with the help of try, catch, finally, and throw statements. The Framework Class Library (FCL) includes a large set of exception classes for dealing with various unforeseen conditions in the normal execution environment.
The .NET Framework provides two exception classes that derive from the common Exception class:
ApplicationExceptionExceptions thrown by the application
SystemExceptionExceptions thrown by the CLR
Both of these child exception classes enjoy the same properties and are differentiated only in the source of the exception they represent. Table 3.1 details some of the important properties of the Exception class, inherited by the exception classes.
Table 3.1 Important Properties of the Exception Class
Property |
Description |
HelpLink |
The URL for a help file associated with the current exception. |
InnerException |
An exception associated with the current exception. This is helpful when a series of exceptions are involved. Each new exception can preserve the information about the previous exception by storing it in this property. |
Message |
A message explaining the error and possibly offering ways to resolve it. |
Source |
The name of the application that caused the error. |
StackTrace |
Retrieves the current stack trace information. You can use this information to locate where an error has occurred. If debugging information is available, the stack trace includes the source file and program line number. |
TargetSite |
The method that threw the exception. |
Handling Exceptions
One of the most fundamental and often most complex tasks of a developer is to design exception-handling procedures to allow an application to recover gracefully from an unexpected or disallowed condition.
The .NET Framework allows exception handling to be performed across languages, across multiple computers, and even across the Component Object Model (COM) and other legacy solutions. Within C#, the most common methods of exception handling involve the try, catch, and finally blocks, in addition to the throw statement.
TIP
try, catch, and finally blocks must be consecutive within code. You cannot have any intervening code separating these blocks when configuring event-handling solutions within your code.
try Block
When processing code that might generate an exception, the code can be placed within a try block, which, in turn, must be followed by one or more catch blocks or a finally block. Exceptions raised cause the CLR to search for the nearest try block (which can be nested within one another) and then pass control to the following catch block, or on to the finally block if no catch block is present in the code.
A try block in its most basic form looks like this:
try { //code that may cause exception }
Any normal code can be placed within the try block, including another try block or calls to methods that include try blocks of their own. When an exception occurs, the CLR finds the nearest try block and passes control to the following associated exception-handling blocks.
TIP
A try block must be followed by one or more catch blocks or by a finally block.
catch Blocks
After an exception is encountered within a try block, control is passed to the following catch blocks or to the finally block. catch blocks are evaluated in order until a match to the exception type is made. The catch blocks should be arranged in order from specific to more general types of the exception.
For example, a DivideByZeroException might match a DivideByZeroException, ArithmeticException, SystemException, or Exception catch block. In the case of multiple catch blocks, only the first matching catch block is executed. All other catch blocks are ignored. If no matching catch block can be found, the exception is passed back to the code that raised the exception and is considered an unhandled exception. This is discussed in greater detail later in this chapter.
NOTE
The default behavior for an unhandled exception is to cause the program to terminate with an error message.
Listing 3.1 shows an example of a try-catch block in use.
Listing 3.1 try-catch Block in Use
private void btnCalculate_Click(object sender, System.EventArgs e) { //put all the code that may require graceful error recovery //in a try block try { decimal decMiles = Convert.ToDecimal(txtMiles.Text); decimal decGallons = Convert.ToDecimal(txtGallons.Text); decimal decEfficiency = decMiles/decGallons; txtEfficiency.Text = String.Format("{0:n}", decEfficiency); } // try block should at least have one catch or a finally block // catch block should be in arranged in order of specific to // the generalized exceptions; // otherwise, compiler generates an error catch (FormatException fe) { string msg = String.Format( "Message: {0}\n Stack Trace:\n {1}", fe.Message, fe.StackTrace); MessageBox.Show(msg, fe.GetType().ToString()); } catch (DivideByZeroException dbze) { string msg = String.Format("Message: {0}\n Stack Trace:\n {1}", dbze.Message, dbze.StackTrace); MessageBox.Show(msg, dbze.GetType().ToString()); } //catches all CLS-compliant exceptions catch(Exception ex) { string msg = String.Format("Message: {0}\n Stack Trace:\n {1}", ex.Message, ex.StackTrace); MessageBox.Show(msg, ex.GetType().ToString()); } //catches all other exception including the //NON-CLS compliant exceptions catch { //just rethrow the exception to the caller throw; } }
Here, an exception raised within the code is thrown to the catch blocks to see if a match is made. When this code is compiled and run, an input zero value will be caught by the second catch block that catches exceptions of type DivideByZeroException, a non-numeric value will be caught by the first catch block that catches exceptions of type FormatException, or a very large numeric value will be caught by the third catch block that catches exceptions of type Exception from which the OverflowException derives. All languages that follow the Common Language Specification (CLS) generate an exception type that derives from System.Exception. Therefore, the catch block that catches exceptions of type Exception will be capable of catching all the exceptions generated by CLS-compliant languages.
The final catch block in the code example is included to handle exceptions generated by nonCLS-compliant languages. An unspecified catch block is the most general form of catch possible and should always be the last catch block if multiple catch blocks are present. The inclusion of the most general catch block prevents an unhandled exception. When the exceptions are caught, they will not cause the program to terminate.
NOTE
Visual C# .NET provides you with checked and unchecked keywords that can be used to enclose a block of statementsfor example, checked {a = c/d};or as an operator when you supply it parameters enclosed in parenthesesfor example, unchecked(c/d). The checked keyword enforces checking of an arithmetic operation for overflow exceptions. If constant values are involved, they are checked for overflow at compile time. The unchecked keyword suppresses overflow checking and does not raise any OverflowException. If any operation results in an overflow while using unchecked, its value is truncated and the result is returned.
finally Block
The finally block includes code that will run whether or not an exception is raised. This is a good location for cleanup code that closes open files or disconnects database connections to release held resources.
The following is an example of code that includes a finally block:
private void btnSave_Click(object sender, System.EventArgs e) { //a StreamWriter writes characters to a stream StreamWriter sw = null; try { sw = new StreamWriter(txtFileName.Text); //Attempt to write the textbox contents in a file foreach(string line in txtText.Lines) sw.WriteLine(line); //This line only executes if there were no exceptions so far MessageBox.Show("Contents written, without any exceptions"); } //catches all CLS-compliant exceptions catch(Exception ex) { string msg = String.Format("Message: {0}\n Stack Trace:\n {1}", ex.Message, ex.StackTrace); MessageBox.Show(msg, ex.GetType().ToString()); goto end; } // finally block is always executed to make sure that the // resources get closed whether or not the exception occurs. // Even if there is any goto statement in a catch or try block the // finally block is first executed before the control // goes to the goto label finally { if (sw != null) sw.Close(); MessageBox.Show( "finally block always executes whether or not exception occurs"); } end: MessageBox.Show("Control is at label: end"); }
The finally block can also be used in conjunction with a try block, without any catch blocks. Exceptions raised are returned as unhandled exceptions in this case. An example of the simplest form of this follows:
try { //Write code to allocate some resources } finally { //Write code to Dispose all allocated resources }
This usage ensures that allocated resources are properly disposed whether the exception occurs. In fact, C# provides a using statement that does the same job, but with less code. A typical use of the using statement is as follows:
// Write code to allocate some resource. // List the allocate resources in a comma-separated list // inside the parentheses, with the following using block using(...) { // use the allocated resource } // Here, the Dispose method is called for all the objects referenced // in the parentheses of the using statement. // There is no need to write any additional code
It is possible to programmatically throw exceptions within the finally block using the throw statement, but this is a bad practice because there might already be unhandled exceptions waiting to be handled.
TIP
try, catch, and finally blocks must be consecutive within code. You cannot have any intervening code separating these blocks when configuring event-handling solutions within your code.
The throw Statement
The throw statement can be used to explicitly throw an exception within your code. This can be used to rethrow a caught exception after performing a task such as generating an event log entry or sending an email notification of the exception. Or, it can be used to raise a custom exception explicitly defined within your code.
NOTE
Throwing an exception is a costly operation and, if carelessly used, can potentially slow down your application. You should throw exceptions with caution and only when essential. You should avoid throwing exceptions for regular control transfer.
An example of the throw statement being used to rethrow a caught exception looks like this in its simplest form:
catch(Exception e) { //TODO: Add code to create an entry in event log throw; }
You can also use the throw statement to throw explicitly created exceptions (that contain a custom error message), as shown here:
string strMessage = "EndDate should be greater than the StartDate"; ArgumentOutOfRangeException newException = new ArgumentOutOfRangeException(strMessage); throw newException;
Creating Custom Exceptions
The .NET Framework CLR includes many standard exception types, but occasionally it is necessary or desirable to create a custom exception to address a specific need within your code. This should be done only if there is not already an existing exception class that satisfies your requirements.
While creating a new custom exception class, Microsoft recommends that you consider the following guidelines:
Derive all programmer-defined custom exception classes from the System.ApplicationException class.
End the name of your custom exception class with the word Exception (for example, MyOwnCustomException).
Implement three constructors with the signatures shown in the following code:
public class MyOwnCustomException : ApplicationException { // Default constructor public MyOwnCustomException () { } // Constructor accepting a single string message public MyOwnCustomException (string message) : base(message) { } // Constructor accepting a string message and an inner exception // that will be wrapped by this custom exception class public MyOwnCustomException(string message, Exception inner) : base(message, inner) { } }
Managing Unhandled Exceptions
The AppDomain class represents the application domain, which is an isolated environment where the CLR-managed applications execute. This class generates an event named UnhandledException whenever an unhandled exception occurs in an application. Unhandled exception can occur if there are no try-catch-finally blocks in the code, or if the existing catch blocks in the code cannot catch the thrown exception.
The UnhandledException event handler receives unhandled exception details through its argument, an object of type UnhandledExceptionEventArgs.
Table 3.2 details the most important properties of the UnhandledExceptionEventArgs class.
Table 3.2 Important Properties of the UnhandledExceptionEventArgs Class
Property |
Description |
ExceptionObject |
Receives the unhandled exception object corresponding to the current domain |
IsTerminating |
Is a Boolean value that indicates whether the CLR is terminating |
An event handler can be attached to the UnhandledException event to take custom actions such as logging the exception-related information. A log maintained over a period can help you to analyze and identify patterns providing useful debugging information. Several techniques can be used to log event-related information:
By using the Windows event log
By using the custom log files
By using the databases such as SQL Server 2000
By sending email notifications
The Windows event log provides the most dependable method of logging because other forms of logging can suffer from loss of network connectivity or file access. You can use the EventLog class to write data to the Windows event logs available in Windows 2000 and later versions of the operating system.
TIP
The option to use the EventLog class is not available in older versions of the Windows operating system, such as Windows 98. It should not be used if the application will be deployed on legacy platforms.
Validating User Input
To make your application as robust as possible, the best solution to invalid or incorrect user input is to prevent the entry of "bad" data as often as possible. Validating user input before hand provides a better solution than very complex error-handling code that might add a great deal of resource overhead to your program. Four basic techniques are used to validate user input:
Restricting the available values by using the proper type of control, configured with a specific list of allowed values. Controls such as RadioButton, ListBox, ComboBox, and CheckBox are often used for this type of validation. Configuring properties of the controls allows additional restriction of user input, such as controlling the case or length of TextBox input.
Restricting data entry through controls by enabling or disabling them based on the state of other controls. As an example of this technique, a set of controls allowing the entry of address information might remain disabled until a valid CustomerID has been selected in another control.
Capturing and evaluating user keystrokes and allowing only acceptable values to be recognized. This might be used to prevent the entry of symbol or alphabetic characters within a control that should hold only numeric characters.
Evaluating a control's data as a whole and warning the user of incorrect or unacceptable values. This is often used to warn a user when attempting to change focus from the control or save the form.
Control-Based Validation
Restriction of allowable values within a control was discussed at greater length in Chapter 2, "Controls on Forms." In addition to simply restricting input to a selection from a list of values, control properties can be configured to further limit possible input values. Of note are the CharacterCasing and MaxLength properties used in text input controls such as the TextBox.
CharacterCasing
The CharacterCasing property of a TextBox control can be used to change all input alphabetic characters to a particular case. The options for the CharacterCasing property are Normal (the default, which does not change the case of input characters), Upper (changes all the characters to uppercase), and Lower (changes all the characters to lowercase).
MaxLength
The MaxLength property of a TextBox or ComboBox is used to restrict the maximum number of characters the user can input into the control. A value of 0 (the default) specifies no specific limit for the number of characters that can be entered by the user. This property does not restrict the length of values that can be set programmatically.
Control-Access Restriction
Manipulating access properties such as the Enabled or ReadOnly properties can restrict data entry access within a control. When a control's Enabled value is set to false, it cannot receive focus. If the ReadOnly property of a TextBox control is set to true, it can still receive focus, allowing users to scroll through its contents while preventing changes.
Keystroke-Level Validation
When a user presses a key, three events are fired in order:
KeyDown
KeyPress
KeyUp
The KeyPress event can be used to intercept input keyboard characters and perform validation tasks through the use of the KeyPressEventArgs class before the KeyUp event is handled. Table 3.4 details some important properties of the KeyPressEventArgs class.
Table 3.4 Important Properties of the KeyPressEventArgs Class
Property |
Description |
Handled |
Whether the event has been handled. |
KeyChar |
The character value corresponding to the pressed key. |
The KeyPress event fires only for keys that generate character values, excluding function, control, and cursor-movement keys. To respond to the excluded keys, you must use the KeyDown and KeyUp events instead. These use the properties of the KeyEventArgs class, detailed in Table 3.5.
Table 3.5 Important Properties of the KeyEventArgs Class
Property |
Description |
Alt |
Is true if the Alt key is pressed; otherwise, is false. |
Control |
Is true if the Ctrl key is pressed; otherwise, is false. |
Handled |
Indicates whether the event has been handled. |
KeyCode |
The keyboard code for the event. Its value is one of the values specified in the Keys enumeration. |
KeyData |
The key code for the pressed key, along with modifier flags that indicate the combination of Ctrl, Shift, and Alt keys that were pressed at the same time. |
KeyValue |
An integer representation of the KeyData property. |
Modifiers |
Modifier flags that indicate which combination of modifier keys (Ctrl, Shift, and Alt) was pressed. |
Shift |
Is true if the Shift key was pressed; otherwise, is false. |
NOTE
By default, only the control, which currently has the focus, responds to the KeyDown, KeyPress, and KeyUp events. However, if you set the KeyPreview property of a form to true, the form can also handle the same three events before the control with the current focus handles them, allowing two tiers of keystroke-level validationat the form level and at the control level.
Field-Level Validation
Validation also can be performed to include the entire value entered within a control by configuring validation code to run before focus is lost or the form is closed. When a user enters or leaves a field, the following events occur in order:
EnterOccurs when a control is entered
GotFocusOccurs when a control receives focus
LeaveOccurs when focus leaves a control
ValidatingOccurs when a control is validating
ValidatedOccurs when a control is finished validating
LostFocusOccurs when a control loses focus
The Validating event is the ideal place to store the validating logic for a field; we discuss the Validating event in the next section.
The Validating Event
The Validating event is ideal for input value validation. You can write code to check the values presented and display an error message to the user or prevent the loss of focus from the current control until the value has been corrected.
The Focus method of the control can be used to redirect focus to the same control programmatically. Alternatively, the Cancel property of the CancelEventArgs object can be set to true, to prevent the transfer of focus from the current control.
TIP
Closing a form fires a Validating event. Therefore, if you want to use the Cancel property of the CancelEventArgs to prevent loss of focus, this will also prevent the user from closing the form. To avoid this, you need to code the event handling to reset the Cancel value only when the mouse is inside the form's client area. This allows the mouse to close the form using the Close button in the title bar.
The Validated event occurs after validation has occurred. It can be used to perform actions based on the validated values, such as enabling or disabling other controls, as discussed previously in this section.
The CausesValidation Property
When using the Validating event to retain the focus in a control until you receive a valid input value, you can prevent the user from being able to obtain help on what constituted a valid input value by clicking another control such as the Help button in the toolbar. This is a result of the default setting (true) of the CausesValidation property of the Button control.
If you set the CausesValidation property of the Help button control to false, the control can act without triggering the Validating event in the control with current focus.
The ErrorProvider Component
The ErrorProvider component provided within the Visual Studio .NET toolbox allows the display of error validation messages. A small icon includes a message that appears as a ToolTip when the user hovers the cursor over the displayed icon. Table 3.6 details the most important members of the ErrorProvider class.
Table 3.6 Important Members of the ErrorProvider Class
Member |
Type |
Description |
BlinkRate |
Property |
Specifies the rate at which the error icon flashes. |
BlinkStyle |
Property |
Specifies a value indicating when the error icon flashes. |
ContainerControl |
Property |
Specifies the parent control of the ErrorProvider control. |
GetError |
Method |
Returns the error description string for the specified control. |
Icon |
Property |
Specifies an icon to display next to the parent control. The icon is displayed only when an error-description string (SetError) has been set for the parent control. |
SetError |
Method |
Sets the error-description string for the specified control. |
SetIconAlignment |
Method |
Specifies the location at which to place an error icon in relation to the control. |
SetIconPadding |
Method |
Specifies the amount of extra space to leave between the specified control and its error icon. |
This component offers many advantages over opening separate message boxes for each possible error, which can confuse users and complicate the desktop. The ErrorProvider component provides a simple user-friendly display that rapidly draws a user's attention to the control failing input validation. Figure 3.2 shows a form that includes an ErrorProvider component.
Figure 3.2 A form displaying an example of the ErrorProvider component.
The following code shows how the ErrorProvider component can be used together with the Validating event to display errors during validation:
private void txtGallons_Validating(object sender, System.ComponentModel.CancelEventArgs e) { try { decimal decGallons = Convert.ToDecimal(txtGallons.Text); if (decGallons > 0) errorProvider1.SetError(txtGallons, ""); else errorProvider1.SetError( txtGallons, "Please enter value > 0"); } catch(Exception ex) { errorProvider1.SetError(txtGallons, ex.Message); } }
In this section, we discussed various techniques that can be used for user input validation. You also learned how the ErrorProvider component can be used to point to errors when the user enters input data on a Windows Form.
Practice Questions
Question 1
You have created the following code segment:
try { //Write code to allocate some resources } finally { //Write code to Dispose all allocated resources }
Which of the following will result from compiling this code, assuming that all other code for your form works properly?
The code will generate an error because it lacks a catch block.
The code will generate an error because it lacks a throw statement.
The code will generate an error because the finally block is placed immediately after the try block.
The code will compile without an error.
Answer D is correct. The code will compile properly because a try block should be followed by either a catch block or a finally block. The code here includes both a try block followed by a finally block. Answer A is incorrect because a try block can be followed by either one or more catch blocks or a finally block (or both). Answer B is incorrect because the throw statement is used to explicitly raise an error and is not required. Answer C is incorrect because a finally block can be placed after a try block.
Question 2
What will be the output of the following code?
try { int num = 100; int den = 0; try { MessageBox.Show("Message1"); int res = num/den; MessageBox.Show("Message2"); } catch(ArithmeticException ae) { MessageBox.Show("Message3"); } MessageBox.Show("Message4"); }
Message1 Message4 Message1 Message2 Message3 Message4 Message1 Message3 Message4 Message1 Message3 Message2 Message4
Answer C is correct. This code first displays Message1 and executes the next line to perform the division. Because the denominator is 0, a DivideByZeroException is raised. Because the code that raises the exception is enclosed in a try block, the program searches for a matching catch block associated with that try block. The code finds a matching catch block with ArithmeticException (that is a base class for the DivideByZeroException exception), which can handle the exception. Therefore, it executes the catch block and displays Message3. After executing the catch block, control comes to the next line after the catch block, and the program displays Message4. Answer A is not correct because the program is capable of locating a catch block that can catch DivideByZeroException. Answer B is not correct because when an exception is raised, the code first searches for the catch block that can handle the exception. Answer D is not correct because after the code in the catch block is executed, control is transferred to the next line after the catch block.
Question 3
How should you arrange catch blocks?
Only one catch block for each try block.
Several catch blocks for a try block, arranged in order starting with Exception and ending with the most specific exception.
Several catch blocks within one try block, arranged starting with the most specific exception and ending with Exception.
The catch blocks should be used only when a finally block is not used.
Answer C is correct. One or more catch blocks can be used with a try block, arranged in order from the most specific exception to the most general; the first matching catch block catches the exception. Answer A is incorrect because you can associate more than one catch block with a try block. Answer B is incorrect because it specifies a reversed order, starting with Exception class. The compiler generates an error if the catch blocks are not arranged from specific to generic types. Answer D is incorrect because catch and finally blocks can both be used together, if desired.
Question 4
You have designed a logon form with two TextBox controls named txtUserName and txtpassword. You want to ensure that the user can enter only lowercase characters in the controls. Which of the following solutions will fulfill this requirement using the simplest method?
Program the KeyPress event of the TextBox controls to convert uppercase letters to lowercase letters.
Create a single event handler that is attached to the KeyPress event of the form. Program this event handler to convert the uppercase letters to lowercase ones.
Set the CharacterCasing property of the Textbox controls to Lower.
Use the CharacterCasing method of the controls to convert the letters to lowercase letters.
Answer C is correct. The simplest method to accomplish this requirement is to set the CharacterCasing property of the two TextBox controls to Lower so that all input characters will be forced to lowercase. Answers A and B could be used to accomplish this task, but this would not be the simplest solution available. Answer D is incorrect because there is no CharacterCasing method for TextBox controls. CharacterCasing is a property that accepts values of Normal, Lower, or Upper.
Question 5
You are creating an order-tracking application using a Visual C# .NET Windows application. When you are unable to track a particular order number entered by the user, you need to raise an exception. Which of the following options will help you to raise an exception?
try block
catch block
finally block
throw statement
Answer D is correct. The throw statement is used to raise an exception. Answer A is not correct because the try block is used to place code that can raise exceptions. Answer B is not correct because the catch block is used to catch and handle exceptions. Answer C is not correct because the finally block is used to insert code that always needs to be executed, such as resource-cleanup code.
Question 6
Which of the following events will fire when the Insert key is pressed? (Choose all correct answers.)
KeyDown
KeyPress
KeyUp
Move
Answers A and C are correct. When control and cursor-navigation keys are pressed, only the KeyDown and KeyUp events are fired. Answer B is incorrect because the KeyPress event occurs only when a keyboard key generates a character.
Question 7
You have a TextBox control and a Help button that the user can press to get help on allowable values. You validate the data entered by the user in the TextBox control. If the user enters an invalid value, you set the focus back in the control using the Cancel property of the CancelEventArgs. A user reports that once he enters invalid data in the text box, he cannot click the Help button. What should you do to correct the problem?
Set the CausesValidation property of the text box to false.
Set the CausesValidation property of the text box to true.
Set the CausesValidation property of the Help button to false.
Set the CausesValidation property of the Help button to true.
Answer C is correct. By setting the CausesValidation property of the Help button to false, you allow it to act without first firing the Validating event in the TextBox, which would return the focus to the TextBox. Answers A and B are incorrect because changing the CausesValidation property of the textbox will not affect the capability of the Help button to be selected. Answer D is incorrect because setting the CausesValidation property of the help button to true (the default value) would result in the same problem experienced by the user.
Question 8
You are designing a Windows Form that enables you to add a new product to the product catalog of your company. You need to validate the controls as the user enters the data. If incorrect data is entered in the field, you should set the focus back to the control and ask the user to enter the correct data. Which of the following events will you use to validate user input?
LostFocus
Validating
Leave
Validated
Answer B is correct. The Validating event is the ideal place to store the validating logic for a field. Answers A and C are not correct because these events are not intended for validation. Properties such as CausesValidation and Cancel, which provide important roles in control validation, affect only the Validating and Validated events. Answer D is not correct because the Validated event is fired after the validation is performed.
Question 9
You have an order entry form. When an exception occurs, you want to get information about the sequence of method calls and the line number in the method where the exception occurs. Which property of your custom exception class that derives from the ApplicationException class should be used?
HelpLink
InnerException
Message
StackTrace
Answer D is correct. The StackTrace method of the Exception class provides information about the method call sequence and line number where the exception occurred. Answer A is incorrect because the HelpLink property specifies the URL for an associated help file. Answer B is incorrect because the InnerException property details an exception associated with the raised exception. Answer C is incorrect because the Message property is used to explain the error or offer possible corrective actions.
Question 10
You want to log events generated by exception-handling code within your application, which will run on standalone systems running Windows 98 and Windows 2000. Which of the four methods of logging is the best single solution able to fulfill this requirement?
Windows event log
Custom log files
Databases such as SQL Server 2000
Email notifications
Answer B is correct. The best solution in this scenario is to use a local custom log file. Answer A is incorrect because some of the systems are running Windows 98, which does not support logging using the event log. Answers C and D are incorrect because standalone systems will not have network access to allow connection to databases or transmission of SMTP messages.
Need to Know More?
Dietel, Harvey M., et al. C#: How to Program. Prentice Hall, 2001.
Richter, Jeffrey. Applied Microsoft .NET Framework Programming. Microsoft Press, 2001.
Windows Forms Community Site: http://www.windowsforms.net/.