Deep C# - Take Exception to Everything |
Written by Mike James | ||||||
Thursday, 12 March 2020 | ||||||
Page 2 of 5
Catch With DetailsThe idea of using types to define exceptions is a perfectly reasonable one as many exceptions include an object of the specified type customised with details of the exception. If you need to process the exception object just include it as a parameter in the catch: catch(DivideByZeroException myException) All exception types are ultimately derived from SystemException. If you don't need the exception object don't include it in the catch - just the type. Notice also that derived types match the parent type. So for example, all exceptions match the SystemException type specification. Of course you can have multiple catch clauses, each dealing with a different type of exception and there is always the finally clause, which is always executed whether or not an exception occurs. For example: try This now handles two types of exception - divide by zero and overflow - but whichever happens the finally clause always displays "Something might be wrong" even if an exception has been handled by one of the previous clauses. It is important to realise that the finally clause isn't a catch-all that handles any exception that you can't be bothered to write a specific catch clause for. Its purpose is to ensure that code is executed irrespective of whether or not an exception occurs. Typically this code does a clean up job that is specific to the code in the try block - e.g. it closes files that are no longer used or disposes of other resources that might have been created. It is also worth knowing that a try block can have a finally even if it doesn't have any catch blocks simply to do a clean up job after the system has displayed a default error message. Another interesting situation that often puzzles the newcomer to exception handing is the simple fact that any variables declared in the try block are local to that block. Similarly any objects created in the block cannot be used within a catch or finally block because the compiler generates an initialised local variable error. What this means is that any objects or variables that you plan to use within the clauses of a try-catch have to be created outside of the block. UsingThe need to clean up after an exception is so common a requirement that there is another way to do it for objects that implement the IDisposable interface. For example, a common idiom is: Bitmap B = new Bitmap(10, 10); which can also be expressed with using: Bitmap B; What is more you can have multiple objects within the using statement and create objects within it: using( Bitmap B = new Bitmap(10, 10)) Catch allIf a finally block isn't about doing things that always have to be done how do you handle any exceptions that don't have specific catch clauses? The solution is to include a catch all clause at the end of the all of the specific catch clauses. For example try If none of the other catch clauses handle the exception then the final catch and the finally are executed. If you place the general catch clause higher in the list of catch clauses then you will see a compile time error message to the effect that you can't have specific catches after a general one. This is an example of the more general rule that more specific catch clauses have to come before more general ones. The reason is that as soon as a catch clause matches the type specification the try catch is complete and no more catch clauses are checked. So a more general catch clause occurring before a more specific one means that the more specific one will never be used. |
||||||
Last Updated ( Thursday, 12 March 2020 ) |