Chapter 7 Abnormal Processing
A great advantage has a great advantage in the General Language Runtime (CLR) for abnormal processing 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 non-calibrated (unchecked) statement
When you perform an operation, it is possible that the calculation result is exceeding the valid range of 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. (Is the C programmer sound 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 convenience, 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 Factorial
4: {
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 use the command line execution program like this
Factorial 2000 p>
is 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 Conframe for the overflow check setting
If you want to control overflow checks to 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 anomalies (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.OverflowException
At factorial.main (System.String []) p>
Now you understand the overflow condition triggered a system.overflowexception exception. 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 don't 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 Factorial
4: {
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 if you use the flag 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 exceptions: 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 a problem with how it handles 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 of C #: p>
. Capture exceptions with try-catch
. Use try-finally to clear exception
. Have all anomalies with try-catch-finally p>
7.2.1 Using TRY and CATCH capture exceptions
You will definitely be very interested - don't prompt users to be annoying news, so that your application continues. 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 OverflowException from Factorial Calculation P>
1: use system; 2:
3: Class Factorial
4: {
5: public static void main (string [] args)
6: {
7: long nfactorial = 1, ncurdig = 1;
8: long ncomputeto = int64.parse (args [0]);
9:
10: TRY
11: {
12: checked
13: {
14: for (; ncurdig <= ncomputeto; ncurdig )
15: nfactorial * = ncurdig;
16:}
17:}
18: Catch (Overflowexception OE)
19: {
20: console.writeline ("computing {0} caused an overflow exception", nComputeTo);
21: Return;
twenty two: }
twenty three:
24: Console.WriteLine ("{0}! Is {1}", ncomputeto, nfactorial;
25:}
26:} p>
To illustrate clearly, I extend some code segments, and I also guarantee that the exception is generated by the Checked statement, even when you have forgotten 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 approach, you cannot get access to an exception object, and the object contains important error information. Generalization exception handling code like this: p>
TRY
{
...
}
Catch (System.exception E)
{
...
} P>
Note that you cannot transfer E objects to a method with REF or OUT modifiers, nor can it give it a different value. P>
7.2.2 Use TRY and FINALLY to clear anomalies
If you care more 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 Factorial
4: {
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: TRY
12: {
13: checked
14: {
15: for (; ncurdig <= ncomputeto; ncurdig )
16: nfactorial * = ncurdig;
17:}
18: Ballfine = true;
19:}
20: Finally
twenty one: {
22: if (! Ballfine)
23: Console.WriteLine ("Computing {0} Caused An Overflow Exception", NComputeTo;
24: ELSE
25: Console.Writeline ("{0}! Is {1}", ncomputeto, nfactorial;
26:}
27:}
28:} p>
You may be guessed by detecting the code. 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 JumpTest
4: {
5: public static void main ()
6: {
7: TRY
8: {
9: console.writeline ("try");
10: goto __leave;
11:}
12: Finally
13: {
14: console.writeline ("finally");
15:}
16:
17: __leave:
18: console.writeline ("__ leave");
19:}
20:} p>
When this application is running, the output result is p>
TRY
Finally
__leave p>
A goto statement cannot withdraw from 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 catchit
4: {
5: public static void main ()
6: {
7: TRY
8: {
Int nthezero = 0;
10: int NRESULT = 10 / NThezero;
11:}
12: Catch (DivideByzeroException Divex)
13: {
14: console.writeline ("Divide By Zero Occurred!");
15:}
16: Catch (Exception EX)
17: {
18: Console.writeline ("Some Other Exception");
19:}
20: Finally
twenty one: {
twenty two: }
twenty three: }
24:} p>
The skill of this example is that 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 of order P>
1: TRY
2: {
3: int NThezero = 0;
4: int NRESULT = 10 / NThezero;
5:}
6: Catch (Exception EX)
7: {
8: console.writeline ("exception" ex.toT7tring ());
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) with the CLR exception and SEH: no exception_continue_execution Identifier Equivalent, it is useful in SEH abnormal filters. 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 trigger an exception
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 provides standard exception P>
Abnormal type description p>
Exception all exception object base class
All errors generated by SystemException
IndexOfficRangeException When the subscript is outside the subscript, run
NullReferenceException When an empty object is ranked when it is referenced
InvalidOperationException When the call to the method is invalid to the current state of the object, some methods are raised by certain methods.
ArgumentException of all parameter abnormal base classes
The argumentnullexception is triggered by the method when the parameter is empty (not allowed).
ArgumentOfRangeException When the parameter is not within a given range, the method is triggered.
Interopexception targets or abnormal base classes in the CLR outside environment
Comexception contains exceptions for HRESULT information for COM classes
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 Reproduction exception
When in the inside 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: try
2: {
3: checked
4: {
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>
Note that I don't have to specify the declared abnormal variables. Although it is optional, you can also write this:
Throw OE;
You must also pay attention to this exception now. P>
7.3.2 Create your own anomaly class
Although predefined exception classes are recommended, you can easily create your own anomaly class for actual occasions. 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: using system;
2:
3: Public class myimportantexception: Exception
4: {
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 ExceptionTestApp
16: {
17: Public Static Void Testthrow ()
18: {
19: throw new myimportantexception ("Something Bad Has Happened.");
20:}
twenty one:
22: Public static void main ()
twenty three: {
24: TRY
25: {
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 abnormal processing "To" and "Don't"
As the last advice, 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 small knot
This chapter begins with an overflow check. 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: In a plurality of examples, you learned that it is different from Win32 structural exception (SEH).