1. Multiple catch Blocks
In the simplest case, a try block has a Catch Block. However, in reality, you often encounter situations where statements containing try blocks can trigger many possible exceptions.
1. based on the previous example, it is assumed that the accelerate () of the car is modified when an invalid parameter (such as a value smaller than 0) is input by the user () the method also raises an argumentoutofrangeexception defined by the base class library.
The first string parameter received by the constructor of the exception class is the name of the error parameter, followed by the information describing the error.
Code:
1 public void Accelerate(int delta)2 {3 if (delta < 0)4 {5 throw new ArgumentOutOfRangeException("delta", "Speed must be greater than zero!");6 }7 ......8 }
The catch logic can now respond to each exception separately:
1 static void Main(string[] args) 2 { 3 Car myCar = new Car("Rusty", 90); 4 5 try 6 { 7 myCar.Accelerate(-10); 8 } 9 catch (CarIsDeadException e)10 {11 Console.WriteLine(e.Message);12 }13 catch (ArgumentOutOfRangeException e)14 {15 Console.WriteLine(e.Message);16 }17 Console.ReadKey();18 }
Output:
Speed must be greater than zero!
Parameter Name: Delta
2. When multiple catch blocks are created, you must note that the first available catch block will be used after an exception is thrown.
To clarify what is the first available Catch Block, check the Code:
As shown in, we try to handle all exceptions, including carisdeadexception and argumentoutrangeexception, by capturing common system. exception. This exception processing logic produces a compilation error. The problem is that the first Catch Block in the (is-a relationship) can handle any exceptions derived from system. exception, including carisdeadexception and argumentoutofrangeexception. Therefore, it will never be able to reach the other two catch blocks!
The Catch Block is structured according to the following principles:
The first Catch Block captures the most specific exception (the top subclass exception), and the last catch captures the most common exception (the exception base class ). System. Exception is often handled in the last catch block.
The following is the correct code:
1 static void main (string [] ARGs) 2 {3 car mycar = new car ("Rusty", 90); 4 5 try 6 {7 mycar. accelerate (-10); 8} 9 catch (carisdeadexception e) 10 {11 console. writeline (E. message); 12} 13 catch (argumentoutofrangeexception e) 14 {15 console. writeline (E. message); 16} 17 catch (exception e) 18 {19 // process all other exceptions 20 console. writeline (E. message); 21} 22 console. readkey (); 23}
II. General catch statements (not recommended)
C # also supports General catch blocks, which do not explicitly receive an object caused by a specified member:
Code:
1 static void Main(string[] args) 2 { 3 Car myCar = new Car("Rusty", 90); 4 5 try 6 { 7 myCar.Accelerate(90); 8 } 9 catch10 {11 Console.WriteLine("Something bad happened...");12 } 13 Console.ReadKey();14 }
Obviously, this is not the best way to handle exceptions, because we cannot obtain meaningful information about errors, so it is not recommended. However, in C #, such a structure is indeed allowed. It can be used to handle all exceptions in general mode.
3. Raise An exception again
In the try block logic, a call stack exception can be thrown to the previous caller again. Just like this, you can use the throw keyword in the catch block. It passes an exception by calling the logical chain.
This is useful when the Catch Block can only handle some of the upcoming errors:
1 static void Main(string[] args) 2 { 3 Car myCar = new Car("Rusty", 90); 4 5 try 6 { 7 myCar.Accelerate(90); 8 } 9 catch (CarIsDeadException e)10 {11 Console.WriteLine("Something bad happened...");12 throw;13 }14 Console.ReadKey();15 }
Running result:
Appear first
Again
Note:
1. carisdeadexception is passed to CLR. This exception is thrown again by the main () method. In this way, the end user will see an error dialog box provided by the system. Generally, you only need to trigger some previously handled exceptions to the caller to properly handle the exceptions.
2. Here, the carisdeadexception object is not explicitly re-ran, but the throw keyword without parameters is used. No new exception object is created, but the original exception object is thrown again. This protects the context of the original target.
3. Internal exceptions
We can trigger an exception when dealing with other exceptions. In the hosts file:
1 catch (CarIsDeadException e)2 {3 FileStream fs = File.Open(@"C:\carErrors.txt", FileMode.Open);4 ...5 }
If the specified file does not exist in drive C, calling file. open () will result in a filenotfoundexception!
If you encounter another exception when handling an exception, it is best to identify the new exception object as an "internal error" in the new object with the same type as the first exception.
The only way to declare an internal error is to use it as a constructor parameter.
Cause:
In the system. Exception base class, public exception innerexception {Get;} is read-only and cannot be assigned a value. However, the constructor public exception (string message, exception innerexception) exists. Therefore, the only way to declare an internal error is to use it as a constructor parameter.
As follows:
1 catch (carisdeadexception E) 2 {3 try 4 {5 filestream FS = file. open (@ "C: \ carerrors.txt", filemode. open); 6} 7 catch (exception E2) 8 {
// Exception that causes a new exception record, and information about the first exception 9 throw new carisdeadexception (E. Message, E2); 10} 11}
Note:
1. In the preceding example, the filenotfoundexception object is passed as the second parameter of carisdeadexception. Once this new object is determined, an exception is thrown to the stack of the next caller. In this example, the next caller is the main () method.
2. Since the main () method does not have the next caller to capture exceptions, we need to present them again in the error dialog box. Just as if an exception is thrown again,Record internal exceptions are generally useful only when the caller can more appropriately capture and handle the first exception.
For example, in this example, if the caller Catch Block logic can use the innerexception attribute to obtain detailed information about an internal exception object, it is useful to record internal exceptions.
4. Finally Blocks
A try/Catch Block may be followed by a Finally block. Finally blocks are not mandatory. They are used to ensure that a group of code statements can always be executed regardless of exceptions.
Usage: In more practical scenarios, when the reader is ready to destroy objects, close files, disconnect database connections, and other operations, add the resource cleanup to finally fast to ensure that the operations are correctly performed.