Avoiding exceptions catches copy-paste in .NET.

Working with the .NET framework I have a service with a set of methods that can throw several types of exceptions: MyException2, MyExc1, Exception ... To ensure proper operation for all methods, each of them contains the following sections:

[WebMethod] void Method1(...) { try { ... required functionality } catch(MyException2 exc) { ... process exception of MyException2 type } catch(MyExc1 exc) { ... process exception of MyExc1 type } catch(Exception exc) { ... process exception of Exception type } ... process and return result if necessary } 

It is very boring to have exactly the same things in EVERY service (each method has different parameters) with exactly the same exception handling functions ...

Is it possible to "group" these catch sections and use only one line (something similar to C ++ macros)? Perhaps something new in .NET 4.0 is related to this topic?

Thanks.

PS Any thoughts are welcome.

+7
copy-paste exception
source share
7 answers

If the exception handling is exactly the same in all of your methods, you can do something like:

 void CallService(Action method) { try { // Execute method method(); } catch(MyException2 exc) { ... process exception of MyException2 type } catch(MyExc1 exc) { ... process exception of MyExc1 type } catch(Exception exc) { ... process exception of Exception type } } 

Then you can simply rewrite your client code:

 int i = 3; string arg = "Foo"; this.CallService( () => this.Method1(i) ); this.CallService( () => this.Method2(arg, 5) ); 

This allows you to use the methods Method1 and Method2:

 void Method1(int arg) { // Leave out exception handling here... ... required functionality ... process and return result if necessary } void Method2(string stringArg, int intArg) { // Leave out exception handling here... ... required functionality ... process and return result if necessary } 
+6
source share

Why not just turn the code into a helper method to do it for you (you can add any new exceptions that you will need in the future to HandleException , which makes it quite scalable)?

 try { ... required functionality } catch (Exception e) { HandleException(e); throw; // only if you need the exception to propagate to caller } private void HandleException(Exception e) { if (e is MyException2) { ... process exception of MyException2 type } else if (e is MyExc1) { ... process exception of MyExc1 type } else { ... process exception of Exception type } } 
+5
source share

I would carefully look at what you are doing to "handle" these exceptions. There is a good chance that you do not need catch blocks, and that you must allow the distribution of exceptions.

+2
source share

In a sudden flash of geekiness (and to show that you could, but most likely you shouldn’t and don’t want to): you can make it all more complicated and reusable by creating on-the-fly functions that contain logic exception handling :

 static class ExceptionHandlerExtensionMethods { // extend to Func<T> as desired public static Action Catching<T>(this Action what, Action<T> handler) where T : Exception { return () => { try { what(); } catch (T ex) { handler(ex); } }; } } 

Now you can implement and reuse the handler functions of special exception types and compose them into exception handling from another method.

To remove redundancy, you can write a helper function that adds the “typical” exception handler functions to what you want to call and call this decorated method instead.

+1
source share

In a similar situation, I did the following. I will show the technique in two stages ...


Step 1. Create a method that provides a specific execution context for another code:

 // this static method is responsible for setting up a context for other code // to run in; specifically, it provides the exception handling "plumbing": public static void guarded(Action action) { // ^^^^^^^^^^^^^ try // actual code to be executed { action(); } catch (SomeExceptionA ea) { // handle exception... } catch (SomeExceptionB eb) { // handle exception... } // etc. } 

Step 2. Apply this context to any piece of code:

Then you simply “end” the exception handling around the actual code in your methods:

 public void MethodA() { guarded(() => // <-- wrap the execution handlers around the following code: { // do something which might throw an exception... }); } public void MethodB() { guarded(() => { // do something which might throw an exception... }); } 

Summary:

The general idea here is to write a function ( guarded in the example above) that sets a specific execution context for other code to run. (The context in this example provides exception handling.) The code to be executed in this context is provided as a lambda function. You can even adapt the context creation function so that the code in the lambda function can return a value.

+1
source share

Using the CallService method from Reed Copsi:

 void DoSomething(object param1, int param2) { this.CallService(() => { // work with param1 and param2 here } } 

For cases where you need to return a value, you may need to duplicate CallService to return a type parameter.

 T CallService<T>(Func<T> callback) { /* ... */ } 
0
source share

I know this is bad practice, but if you have the same error handling in every catch statement, why not just use the last catch statement as catch?

This, of course, assumes that all of your exceptions are inherited from Exception.

-3
source share

All Articles