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.
7.1 Checked and non-check (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)
Listing 7.1 Calculating a number of steps
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:}
When you use the command line to execute the program like this
Factorial 2000
The result 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
Now when you perform an application with a 2000 parameter, the CLR informs you that overflow exceptions (see Figure 7.1).
Figure 7.1 allows an overflow to abnormally, and the classification code has an exception.
Press the OK button to leave the dialog to reveal the exception information:
Exception Occurred: System.OverflowException
At factorial.main (system.string & #;)
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.
Overflow check 1 in list 7.2 classification 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:}
Even if you use the logo Checked-compiled this code, in line 13, the overflow check will still check the multiplication. The error message is consistent.
The statement that displays the opposite behavior is unchecked. Even if the overflow check is allowed (add Checked flag to the compiler), the code hosted by the unchecked statement will not cause overflow exceptions:
unchecked
{
Nfactorial * = ncurdig;
}
7.2 Exception Processing 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.
The Following Three Sections Introduce C # 's Exception-Handling Statements:
The following three sections describe the exception handling statement of the C #:
. Capture exceptions with try-catch
. Use try-finally to clear exception
. Treat all exceptions with try-catch-finally
7.2.1 capture exceptions using TRY and CATCH
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.
Listing 7.3 Capture OverflowException triggered by Factorial Calculation
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:
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:}
To illustrate clear, I extend 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.
Try
{
...
}
Catch
{
...
}
However, through this way, you cannot get access to an exception object, and the object contains important error information. Generalization exception handling code like this:
Try
{
...
}
Catch (System.exception E)
{
...
}
Note that you can't transfer E objects to a method with a REF or OUT modifier, or you can't assign it a different value.
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.
Listing 7.4 Processing exceptions in a finally statement
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:}
By detecting the code, you may guess that finally will be executed even if it does not trigger an exception. 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.
Listing 7.5 Jump from the TRY sentence to Finally statement
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:}
When this application is running, the output result is
Tryfinally__leave
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.
7.2.3 Handling All Options Applications Using Try-Catch-Finally Most Possible Ways are combined with two error handling technologies - capture errors, clear and proceed. 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.
Listing 7.6 Implement multiple CATCH statements
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 (Exception EX) 17: {18: Console.WriteLine ("Some Other Exception"); 19 :} 20: Finally21: {22:} 23:} 24:} This example is the skill of this example, which 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.
Listing 7.7 Catch statement in order inappropriate
1: try2: {3: int NThezero = 0; 4: Int nresult = 10 / NThezero; 5:} 6: Catch (Exception EX) 7: {8: console.writeline ("exception" ex.toTostring ()) ; 9:} 10: Catch (DivideByzeroException Divex) 11: {12: console.writeline ("Never Going to See That); 13:}
The compiler will capture a small error and report this error similar to this: WrongCatch.cs (10, 9): Error CS0160: a Previous Catch Clause Already Catches All Exceptions of this or a super type ('system.exception')
Finally, I have to tell a shortcomings (or different) of the CLR exception to SEH: There is no equivalent of the Exception_Continue_execution Identifier, which is useful in the SEH exception filter. 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.
7.3 Advanced Exercise When you have to capture anomalies, others must first lead to anomalies. Moreover, not only others can trigger, you can also be responsible. It is quite simple:
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. Table 7.1 Runtime Provided by Runtime
Abnormal type description
Exception All error based class SystemException runtime Generated Based class indexoutofrangeException When a quaternary subscript is run out of the range, running NullReferenceException When an empty object is referenced when an empty object is quoted, INVALIDOPERATIONEXCEPTION is called to objects When the current state is invalid, the base class of ArgumentNullexCeption by the argumentnullexception of all parameter exceptions is empty (not allowed), and the method is triggered by the method when the parameter is not in a given range. When the parameter is not in a given range, the interopexception target is initiated. The abnormal base class comXception in or occurs in the CLR outside environment, the exception of the HRESULT information of the COM class, the exception of the WIN32 structure is enabling the WIN32 structure, 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.
7.3.1 Renewing an exception When you are in the interior of a Catch statement, you may decide to trigger an exception that is currently processed, leaving further processing to some external TRY-CATCH statements. Examples of the method are shown in Listing 7.8.
Listing 7.8 Recommoding an exception
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:}
Note that 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.
7.3.2 Creating your own anomaly although it is recommended to use a predefined exception class, for actual occasions, creating your own anomalies may 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
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:} 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.
7.4 Exceptions of "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.