".NET Program Pioneer C #" Chapter VII Operational Handling Christoph Wille | 2001-9-3
Seventh chapter Overpotency General Language Runtime (CLR) has a large advantage that exception handling is standardized in crosswords. An exception initiated in C # can be processed in Visual Basic customers. No longer HRESULTS or ISUPPORTERRORINFO interface. Although the coverage of cross-language abnormal processing is very wide, this chapter completely discusses C # abnormal processing. You slightly change the overflow processing behavior of the compiler, and then interesting things start: you have handled this exception. To add more means, then trigger an exception you created. P>
7.1 Checked and Nelfly Veribed Statement When you perform an operation, it is possible to generate a valid range of the calculation result to exceed the result variable data type. This situation is called overflow, which you will be notified in some way in accordance with different programming languages - or not notified at all. (C programmer sounds familiar?) So, how do c # handle overflow? To find out its default behavior, please see the example of the steps mentioned earlier in this book. (For the convenience of see it, the previous example is given in Listing 7.1) p>
Listing 7.1 Calculating a number of steps p>
1: using system; 2: 3: Class Factorial4: {5: public static void main (String [] args) 6: {7: long nFactorial = 1; 8: long ncomputeto = int64.parse (args [0]); 9: 10: long ncurdig = 1; 11: for (ncurdig = 1; ncurdig <= ncomputeto; ncurdig ) 12: nFactorial * = ncurdig; 13: 14: console.writeline ("{0}! is {1}", ncomputeto, nfactorial; 15:} 16:} < / P>
When you like this to use the command line execution program, Factorial 2000
results are 0, and there is no happening. Therefore, it is assumed that C # silently handles overflows and not clearly warns you safe. You can change this behavior by giving the entire application (compiler switch) or in the statement level. The following two sections solve a solution. 7.1.1 Settings the overflow check settings If you want to control overflow checks the entire application, the C # compiler settings are what you want to find. By default, overflow checks are disabled. To clearly ask it, run the following compiler command: CSC Factorial.cs / Checked P>
Now when you perform an application with a 2000 parameter, the CLR informs you to overflow anomaly (see Figure 7.1). P>
Figure 7.1 allows an overflow anomaly, and the classification code has an exception. P>
Press the OK button to leave the dialog to reveal the exception information: Exception Occurred: system.overflowexceptionat Factorial.main (System.String []) p>
Now you know that overflow conditions have triggered one System.overflowexception is abnormal.
In the next section, how to capture and handle the exceptions that occur after we complete the syntax checks? 7.1.2 Syntax Overflow Check If you do not want to allow overflow checks to the entire application, you may be comfortable to give some code segments. For this occasion, you may use the checklist as you are displayed in Listing 7.2. P>
Listing 7.2 Overflow Calibration in Section Calculation p>
1: use system; 2: 3: Class Factorial4: {5: Public Static Void Main (String [] ARGS) 6: {7: long nFactorial = 1; 8: long ncomputeto = int64.parse (args [0]); 9: 10: long ncurdig = 1; 11: 12: for (ncurdig = 1; ncurdig <= ncomputeto; ncurdig ) 13 : checked {nfactorial * = ncurdig;} 14: 15: console.writeline ("{0}! is {1}", ncomputeto, nfactorial; 16:} 17:} p>
even as you Using the logo Checked-compiled this code, in line 13, the overflow check will still check the multiplication. The error message is consistent. P>
Display the statement of the opposite behavior is unchecked. Even if the overflow check is allowed (add Checked flag to the compiler), the code enclosed by the unchecked statement will not cause overflow exception: p>
unchecked {nfactorial * = ncurdig;} P>
p>
7.2 Exception Handling Statement Since you know how to generate an exception (you will find more methods, believe me), there is still how to handle it. If you are a C Win32 programmer, it must be familiar with SEH (structural exception handling). You will find comfort, the commands in the C # are almost the same, and they also operate in a similar manner. P>
The Following Three Sections Introduce C # 's Exception-Handling Statements: The following three sections describe the exception handling statement: p>
. Capture exceptions with try-catch. Use try-finally to clear the exception. Have all the exceptions with try-catch-finally p>
7.2.1 You will definitely be very interested in one thing. You will definitely be very interested - don't prompt the user's annual event, So your app continues to do. In this way, you must capture (handle) the exception. The statement used is TRY and CATCH. The TRY contains statements that may generate an exception, and Catch processes an exception, if there is an abnormality exists. Listing 7.3 Using TRY and CATCH to achieve exception processing for OverflowException.
P>
Listing 7.3 Capture of OverflowException from Factorial Calculation p>
1: use system; 2: 3: Class Factorial4: {5: Public static void main (String [] args) 6 : {7: long nFactorial = 1, ncurdig = 1; 8: long ncomputeto = int64.parse (args [0]); 9: 10: try11: {12: checked13: {14: for; NCURDIG ) 15: nFactorial * = ncurdig; 16:} 17:} 18: Catch (overflowexception oe) 19: {20: console.writeline ("Computing {0} Caused An Overflow Exception", NComputeTo; 21: Return; 22 } 23: 24: Console.Writeline ("{0}! Is {1}", ncomputeto, nfactorial; 25:} 26:} p>
To illustrate clear, I extended some code segments And I also guarantee that the exception is generated by the Checked statement, even when you forget the compiler settings. As you can see, abnormal treatment is not bother. All you want to do is: In the TRY statement, it contains easy generation code, then captures exception, which is in this example. The OverflowException type. No matter when an exception is triggered, the code in the catch segment will pay attention to appropriate processing. If you don't know which exception will be expected, but still want to be safe, simply ignore the type of exception. P>
try {...} catch {...} p>
However, through this way, you cannot get access to an exception object, and the object contains important error information. Generalization exception processing code like this: p>
try {...} catch (system.exception e) {...} p>
Note, you can't use REF or OUT modifier Pass the E object to a method, or you can't assign it a different value. P>
7.2.2 Use TRY and Finally to clear an exception If you are more concerned about cleaning instead of error handling, try and finally will get your favorite. It not only suppresses the error message, but all the code contained in the Finally block is still executed after an exception being thus being thrown. Although the program is not stopped normally, you can also get a message for the user, as shown in Listing 7.4.
P>
Listing 7.4 Processing exception in the finally statement p>
1: using system; 2: 3: Class Factorial4: {5: public static void main (String [] args) 6: { 7: long nFactorial = 1, ncurdig = 1; 8: long ncomputeto = int64.parse (args [0]); 9: bool ballfine = false; 10: 11: Try12: {13: checked14: {15: for NCURDIG <= NComputeTo; NCURDIG ) 16: nFactorial * = ncurdig; 17:} 18: ballfine = true; 19:} 20: Finally21: {22: if (! ballfine) 23: console.writeline ("computing {0} Cause) An Overflow Exception ", NComputeTo); 24: Else25: console.writeline (" {0}! is {1} ", ncomputeto, nfactorial; 26:} 27:} 28:} p>
by detection This code, you may be guessed, even if there is no exception handling, Finally is also executed. This is true - the code in Finally is always executed, regardless of whether there is an abnormal condition. To illustrate how to provide some meaningful information to the user in both cases, I introduced a new variable Ballfine. Ballfine tells the finally paragraph, whether it is because an exception is only called because the calculation is successfully completed. As a habit of SEH programmers, you may think, is there a statement with the __leave statement equivalent, this statement is used in C . If you still don't know, in the __leave statement in C is used to terminate the execution code in the TRY segment, and immediately jump to the Finally segment. Bad news, there is no __leave statement in the C #. However, the code in Listing 7.5 demonstrates a solution you can implement. P>
Listing 7.5 Jump from the TRY Statement to Finally Statement P>
1: USING SYSTEM; 2: 3: Class JumpTest4: {5: Public Static Void Main () 6: {7: Try8: {9: Console.Writeline ("try"); 10: goto __leave; 11:} 12: Finally13: {14: console.writeline ("finally"); 15:} 16: 17: __leave: 18: Console .Writeline ("__ leave"); 19:} 20:} p>
When this application is running, the output is p>
tryfinally__leave p>
a goto statement cannot Exit a Finally segment. Even put the GOTO statement in the TRY sentence, or immediately return to the Finally segment. Therefore, GOTO just leaves the TRY segment and jumps to the Finally segment. The __leave label can be reached until the code in finally is running. In this way, you can imitate the __leave statement used in SEH.
Because, you may doubt the goto statement is ignored because it is the last statement in the TRY statement and the control is automatically transferred to Finally. To prove that it is not the case, try the GOTO statement before the console.writeLine method call. Although you get a warning for the compiler because you don't reach the code, you will see that the GOTO statement is actually executed and there is no output generated for the TRY string. P>
7.2.3 Using try-catch-finally to process all exception applications The most possible way to merge two error handling technologies - capture errors, clear, and proceed to execute applications. All you have to do is using Try, Catch, and Finally statements in the error handling code. Listing 7.6 shows the way to process zero errors. P>
Listing 7.6 Implement multiple CATCH statements p>
1: using system; 2: 3: Class catchit4: {5: public static void main () 6: {7: try8: { 9: int NThezero = 0; 10: int NRESULT = 10 / NThezero; 11:} 12: Catch (DivideByzeroException Divex) 13: {14: console.writeline ("Divide By Zero Occurred!"); 15:} 16: catch ("Some Other Exception"); 19:} 20: Finally21: {22:} 23:} 24:} p>
This example is the skill, It contains multiple CATCH statements. The first captured DivideByzeroException exception, and the second Catch statement handles all the remaining exceptions by capturing normal abnormalities. You must always capture a specific exception first, then it is an ordinary exception. What happens if you caught anomalies in this order? The code in Listing 7.7 is described. P>
Listing 7.7 Catch statement of the order 7.7 P>
1: try2: {3: int nthezero = 0; 4: int NRESULT = 10 / NThezero; 5:} 6: catch ( Exception EX) 7: {8: console.writeline ("exception" ex.Writeline ()); 9:} 10: catch (DivideByzeroException Divex) 11: {12: console.writeline ("Never Going to See That") 13:} p>
The compiler will capture a small error and report this error like this: WrongCatch.cs (10, 9): Error CS0160: a Previous Catch Clause Already Catches All Exceptions of this OR A Super Type ('system.exception') p>
finally, I must tell a shortcoming (or different) of the CLR exception to SEH: there is an equivalent of an Exception_Continue_execution identifier, it is in the SEH exception filter It is useful in it. Basically, Exception_Continue_execution allows you to re-execute code snippet responsible for abnormalities. You have the opportunity to change variables before re-executing.
I personally like the technology to use access violations, implement memory allocation as needed. P>
7.3 Advanced Experience When you have to capture anomalies, others must first initiate an exception. Moreover, not only others can trigger, you can also be responsible. It is quite simple: p>
throw new argumentException ("Argument CAN't BE 5"); what you need is the throw statement and an appropriate exception class. I have selected an exception to this example from the list provided by Table 7.1. P>
Table 7.1 Runtime The standard exception provided P>
Exception type Description p>
exception All anomaly objects The base class of the base class systemException All errors generated by all errors INDEXOFRANGEEXCEPTION When the subscript of an array is out of the range, running NullReferenceException when an empty object is quoted when an empty object is cited, and an invalidOperationException is invalid when the call to the method is invalid. The current state of the object is invalidated by some methods. Argumentnullexception When the parameter is empty (not allowed), the method that causes ArgumentOfRangeException when the parameter is not within a given range, and the method that causes an interopexception target or an exception class of an anomaly in the CLR outside the environment. Comexception contains the HRESULT of the COM class. Information for exceptions Sehexception package WIN32 structure exception processing information exception p>
However, in the inside of the catch statement, you already have an unusual disposal, you don't have to create a new exception. There may be no exception in Table 7.1 that meets your special requirements - Why don't you create a new exception? In the junction, it is involved in these two topics. P>
7.3.1 Renevab An exception When you are in the interior of a catch statement, you may decide to trigger an exception that is currently re-processing, leaving further processes to some external TRY-CATCH statements. Examples of the method are shown in Listing 7.8. P>
Listing 7.8 Recommoding an exception P>
1: try2: {3: checked4: {5: for (; ncurdig <= nComputeTo; ncurdig ) 6: nfactorial * = ncurdig; 7 :} 8:} 9: Catch (overflowexception oe) 10: {11: console.writeline ("computing {0} caused an overflow exception", nComputeTo); 12: throw; 13:} p>
pay attention I don't have to specify the declared abnormal variables. Although it is optional, you can also write: throw oe; now you must pay attention to this exception. P>
7.3.2 Creating your own anomaly although it is recommended to use a predefined exception class, for actual occasions, you can easily be convenient. Create your own anomaly class, allowing your exception class to take different means according to the exception class. The anomaly class Myimportantexception appears in Listing 7.9 follows two rules: First, it ends the class name with Exception. Second, it implements all three recommended universal structures. You should also follow these rules.
Listing 7.9 Implementing your own anomaly class MyImportantexception p>
1: use system; 2: 3: public class myimportantexception: Exception4: {5: public myimportantexception () 6:: Base () {} 7: 8: public MyImportantException (string message) 9:: base (message) {} 10: 11: public MyImportantException (string message, Exception inner) 12:: base (message, inner) {} 13:} 14: 15: public class ExceptionTestApp16: { 17: Public static void testthrow () 18: {19: throw new myimportantexception ("Something Bad Has Happened."); 20:} 21: 22: Public Static Void Main () 23: {24: try25: {26: exceptionTestApp .Testthrow (); 27:} 28: Catch (Exception E) 29: {30: console.writeline (e); 31:} 32:} 33:} p>
As you can see, MyIMPortantexception anomaly class cannot implement any special features, but it is completely based on the System.Exception class. The remainder of the program tests the new anomaly class and uses a Catch statement for the System.Exception class. If there is no special implementation but only gives MyImportantexception defines three constructor, create it what does it make? It is an important type - you can use it in a catch statement, replacing more common anomaly. Customer code that may trigger your new exception can play a role in accordance with the specified CatCH code. When writing a class library with your own namespace, you should put an exception to the name space. Although it does not appear in this example, you should also use the appropriate properties to expand your exception class for extended error messages. P>
7.4 Exception Handling "To" and "Don't" as the last admissions, here is the list of abnormally caused and deal with what to do and do not do:. When you causon an exception, you must provide meaningful text. . To trigger an exception is only true that the condition is true; that is, when a normal return value is not satisfied. . If your method or property is passed a bad parameter, you want to trigger an argumentException exception. . When the calling operation is not suitable for the current state of the object, it is necessary to trigger an invalidopertyException exception. . To trigger the most suitable exception. . To use the link exception, they allow you to track anomalous tree. . Do not use an exception for normal or expected errors. . Do not use an exception for the normal control of the process. . Do not trigger NullReferenceException or IndexOutofRangeException in the method. P>
7.5 Summary This chapter is started from introducing overflow checks. You can use the compiler switch (default is off) so that the entire application allows or disables overflow checks. If you need fine-tuning control, you can use the checksum and non-verified statement, which allows you to perform a code or not using overflow checks, although not given the application. When an overflow occurs, an exception is triggered. How to deal with exception depends on you. I propose a variety of ways, including you most likely to use: Try, catch, and finally statements throughout the app: