You can handle exceptions in Visual C# .NET programs by using a combination of these exception handling statements: try , catch , finally , and throw . The try BlockYou should place code that might cause exceptions in a try block. A typical try block looks similar to the following: try { // code that may cause exception } When an exception occurs at any point, rather than executing any further, the CLR searches for the nearest try block that encloses the exceptional code. The control is then passed to a matching catch block (if any) and then to the finally block (if any) associated with this try block. A try block cannot exist on its own; it must be immediately followed either by one or more catch blocks or by a finally block. The catch BlockYou can have several catch blocks immediately following a try block. When an exception occurs in a statement placed inside the try block, the CLR looks for a matching catch block capable of handling that type of exception. A typical try - catch block looks like this: try { // code that may cause exception } catch( ExceptionTypeA ) { // Statements to handle errors // occurring in the associated try block } catch( ExceptionTypeB ) { // Statements to handle errors occurring // in the associated try block } The formula the CLR uses to match the exception is simple: It looks for the first catch block with either the same exception or any of the exception's base classes. For example, a DivideByZeroException exception would match with any of these exceptions: DivideByZeroException , ArithmeticException , SystemException , and Exception . In the case of multiple catch blocks, only the first matching catch block is executed and all other catch blocks are ignored.
When you write multiple catch blocks, you need to arrange them from specific exception types to more general exception types. For example, the catch block for catching the DivideByZeroException exception should always precede the catch block for catching the ArithmeticException exception because the DivideByZeroException exception derives from the ArithmeticException exception and is therefore more specific than ArithmeticException . The compiler flags an error if you do not follow this rule. A try block need not necessarily have a catch block associated with it; however, in that case, it must have a finally block associated with it. The finally BlockYou use the finally block to write cleanup code that maintains your application in a consistent state and preserves the external environment. For example, you can write code to close files, database connections, and related input/output (I/O) resources in a finally block. A try block doesn't have to have an associated finally block. However, if you do write a finally block, you cannot have more than one, and the finally block must appear after all the catch blocks. The finally block can be used in the form of a try - finally block without any catch block between them. Here's an example: try { // Write code to allocate some resources } finally { // Write code to dispose all allocated resources } This use ensures that allocated resources are properly disposed of, no matter what happens in the try block. In fact, Visual C# .NET provides a using statement that does exactly the same job but with less code to write. A typical use of the using statement is as follows : // Write code to allocate some resource list the allocated resources in a comma-separated list inside the parentheses of the using block using(...) { // use the allocated resource } // Here, the Dispose() method is called automatically for all the // objects referenced in the parentheses of the using statement The following example shows you how to use a try - catch - finally block to handle exceptions:
The throw StatementA throw statement explicitly generates an exception in code. You use throw when a particular path in code results in an anomalous situation. There are two ways you can use the throw statement. In its simplest form, you can just rethrow the exception in a catch block: catch(Exception e) { //TODO: Add code to create an entry in event log throw; } This use of the throw statement rethrows the exception that was just caught. It can be useful in situations in which you do not want to handle the exception yourself but would like to take other actions (for example, recording the error in an event log or sending an email notification about the error) when an exception occurs. Then, you can pass the exception as is to its caller. The second way of using a throw statement is to use it to throw explicitly created exceptions, as in this example: string strMessage = "EndDate should be greater than the StartDate"; ArgumentOutOfRangeException newException = new ArgumentOutOfRangeException(strMessage); throw newException; In this example, you first create a new instance of the ArgumentOutOfRangeException object and associate a custom error message with it; then you throw the newly created exception. You are not required to put this usage of the throw statement inside a catch block because you are just creating and throwing a new exception, rather than rethrowing an existing one. You typically use this technique to raise your own custom exceptions.
An alternative way of rethrowing an exception is to throw it after wrapping it with additional useful information, like so: catch(ArgumentNullException ane) { // TODO: Add code to create an entry in the log file string strMessage = "CustomerID cannot be null"; ArgumentNullException newException = new ArgumentNullException(strMessage, ane); throw newException; } You might need to catch an exception that you cannot handle completely. You would then perform any required processing and throw a more relevant and informative exception to the caller code so it can perform the rest of the processing. In this case, you can create a new exception whose constructor wraps the previously caught exception in the new exception's InnerException property. The caller code then has more information available to handle the exception appropriately. |