C # Sharp experience
Nanjing Institute of Posts and Telecommunications
Li Jianzhong (
Lijianzhong@263.net.cn
)
Lecture 2
Exception Handling
Exception Handling
??????? Structured exception handling is a necessary part of component design in a modern distributed environment. During the runtime of the. NET general language, it provides solid support for exception handling from the underlying structure. In C #, the exception object is designed as a class that encapsulates various exception information (system. exception and its inherited subclass. Similar to the interface, it is recommended to name it with the suffix "exception", but this is not required ), the "try-catch-finally" Statement and exception object together provide a package of services from exception detection, exception capturing, and handling for the C # component design. Let's look at a typical example:
Using system;
Class Test
{
???? Public static void main ()
???? {
???????? Int x = 0;
???????? Try
???????? {
???????????? Int y = 10/X; // exception in Division by zero
???????????? Console. writeline ("Try end !");
????????}
???????? Catch (dividebyzeroexception E)
???????? {
???????????? Console. writeline ("dividebyzeroexception -->" + E );
????????}
???????? Catch (exception E)
???????? {
???????????? Console. writeline ("general exception -->" + E );
????????}
????}???
}
The following output is generated:
Dividebyzeroexception --> system. dividebyzeroexception: attempted to divide by zero.
??? At test. Main ()
In the above try statement, we specifically perform the division by zero operation to generate a "Division by zero exception". In the first catch statement, we caught the "Division by zero exception" -- dividebyzeroexception, this is due to the type specified in catch. We can also see from the results that our second catch statement did not catch any other exceptions. Although this example is short, it reveals the basic model of exception handling.
??????? First, we place the statements that may cause exceptions in the try statement block so that the exceptions in the code can be detected and passed to the catch statement. A catch statement can contain parameters or not. The type of the catch statement must be system. Exception and its inherited subclass. A catch statement with parameters only captures exceptions of the specified type. Other exceptions are not handled. A catch statement without parameters is equivalent to an exception of the system. Exception type (that is, all exceptions), except that the exception variable (such as E in the preceding example) cannot be obtained ). A try block can be followed by multiple catch statements to capture different exception types. Note the order of multiple catch statements. The parameter type in the catch statement cannot be a subclass of the previous type or be of the same type as the previous parameter type. No parameter is equivalent to system. exception type. This rule is natural in the sense of handling specific types of exceptions -- if the aexception type is a base class of the bexception type, if a bexception type exception occurs, catch (aexception E) it can also be captured, so that the following will not catch bexception type exceptions, catch (bexception e) will also be meaningless. C # The Compiler reports an error in this case.
??????? What if the parameter type of our catch statement does not match the exception type detected by the try statement? In this case, an exception is thrown in the method body of the statement. If the method to call this method does not have a corresponding detection and capturing mechanism, the exception is thrown until it is captured, or the main function is thrown to the entry point of the application, causing program execution to be interrupted due to exceptions. The mechanism for throwing such exceptions is also applicable to exceptions that occur outside the try statement-the same effect is not captured but not detected!
??????? Note that once an exception occurs to the program, the subsequent code will not be executed! Console. writeline ("Try end!") in the preceding example !") The preceding code is not executed because of a "Division by zero exception. This also determines that our code can only be caught once and can only catch once!
However, what if we need to execute some urgent code (such as closing open files and Network Ports) in case of exceptions or exceptions in our program logic? C # provides finally statements to solve this problem. Finally statements cannot be used independently. They can be used together with try and catch statements. Try, catch, and finally are combined to form a try-catch-finally statement. See the following example:
Using system;
Public class test
{
???? Public static void main ()
???? {
???????? Try
???????? {
???????????? Console. writeline ("try ...");
???????????? Throw new nullreferenceexception (); // throw an exception
????????}
???????? Catch (nullreferenceexception E)
???????? {
???????????? Console. writeline ("nullreferenceexception: {0}", e );
????????}
???????? Catch (exception E)
???????? {
???????????? Console. writeline ("exception: {0}", e );
????????}
???????? Finally
???????? {
???????????? Console. writeline ("finally ...");
????????}
????}
}
Program output:
Try...
Nullreferenceexception: system. nullreferenceexception: object reference not set to an instance of an object.
??? At test. Main ()
Finally...
The finally statement is executed even if an exception is thrown. Try statements can also be combined with finally statements to form a try-finally statement. After the try-finally statement detects an exception, it simply throws it and does not capture it. However, after the exception is handled (caught by the catch statement that calls its method, or the execution environment is interrupted when it reaches the main function entry point), The finally statement is still executed. Of course, there can only be one finally statement block, which is self-evident.
??????? In the above Code, the throw statement is used to throw an exception. What is the problem? In our code design, we often have to throw a specific exception that violates the conditions or exceptions set by the program design. At this time, the throw statement is very useful. Let's look at the following example:
Using system;
Public class myexception: applicationexception
{
???? Public myexception (string message): Base (Message)
???? {
????}
???? Public myexception (string message, exception inner): Base (message, inner)
???? {
????}???
}
Public class myclass
{
???? Public static void exmethod ()
???? {
???????? Throw new myexception ("exception in exmethod ");
????}
???? Public static void mymethod ()
???? {
???????? Try
???????? {
???????????? Exmethod ();
????????}
???????? Catch (exception E)
???????? {
???????????? Throw new myexception ("exception in mymethod", e );
????????}
????}
}
Public class test
{
???? Public static void main ()
???? {
???????? Try
???????? {
???????????? Myclass. mymethod ();
????????}
???????? Catch (exception E)
???????? {
???????????? Console. writeline (E );
???????????? Console. writeline ();
???????????? Console. writeline (E. getbaseexception ());
????????}
????}
}
Program output:
Myexception: exception in mymethod ---> myexception: exception in exmethod
??? At myclass. exmethod ()
??? At myclass. mymethod ()
??? --- End of inner exception stack trace ---
??? At myclass. mymethod ()
??? At test. Main ()
Myexception: exception in exmethod
??? At myclass. exmethod ()
??? At myclass. mymethod ()
In the above example, we designed our own exception class myexception and simply applied this exception class in our own class design. The test program shows its processing and tracing of exceptions in calling multiple methods. Among them, E. getbaseexception () is to call the getbaseexception () method of system. Exception to obtain the first exception that caused exception E. If not, e itself will be returned. Many methods and attributes of system. Exception provide us with a good description and Tracing Service for exceptions. It is a good starting point for us to understand exceptions in application exceptions, design exceptions, and exceptions.
CheckedAnd unchecked
??????? An "overflow exception" -- system. overflowexception is not really an "exception" in some algorithms. On the contrary, such overflow is often used by programs. C # introduce the checked and unchecked keywords to control the requirements in this special case. They can all be added before a statement block (for example, checked {......}), Or before an arithmetic expression (for example, unchecked (x + y )). The statement or expression of the checked flag in it. If Arithmetic overflow occurs, an exception of the system. overflowexception type is thrown. When the unchecked flag overflows in arithmetic mode, no exception is thrown. The following is a demo:
Using system;
Class Test
{
???? Static void main ()
???? {
???????? Int num1 = 100000, num2 = 100000, result = 0;
???????? Checked
???????? {
???????????? Try
???????????? {
???????????????? Result = num1 * num2;
????????????}
???????????? Catch (system. overflowexception E)
???????????? {
???????????????? Console. writeline (E );
????????????}
???????????? Finally
???????????? {
???????????????? Console. writeline (result );
????????????}
????????}
???????? Unchecked
???????? {
???????????? Try
???????????? {
???????????????? Result = num1 * num2;
????????????}
???????????? Catch (system. overflowexception E)
???????????? {
???????????????? Console. writeline (E );
????????????}
???????????? Finally
???????????? {
???????????????? Console. writeline (result );
????????????}
????????}
????}
}
Program output:
System. overflowexception: arithmetic operation resulted in an overflow.
??? At test. Main ()
0
1410065408
??????? We can see that the same arithmetic operation throws an overflow exception with checked, and unchecked only discards the overflow bit to obtain the remaining 32-bit decimal integer value. It is worth noting that the "/checked" compiler option can be used to specify the code of the entire file as the checked syntax. If not specified, the default value is unchecked. If the checked or unchecked flag is specified in the program code and the checked compiler option is available, the checked semantics is included in all the Code except the Code marked as unchecked.