DRY with various attempt statements and identical Catch expressions

So, I have the following code block inside the method: (all variables are local)

// ... try { if (postXml != null) using (StreamWriter writer = new StreamWriter(req.GetRequestStream())) writer.Write(postXml.ToString()); } catch (WebException ex) { HttpWebResponse response = ex.Response as HttpWebResponse; if (response != null) result = HandleOtherResponse(response, out status); else result = HandleBadResponse(ex.ToString(), out status); } catch (Exception ex) { result = HandleBadResponse(ex.ToString(), out status); } if (result == null) { try { HttpWebResponse response = req.GetResponse() as HttpWebResponse; result = HandleOtherResponse(response, out status); } catch (WebException ex) { HttpWebResponse response = ex.Response as HttpWebResponse; if (response != null) result = HandleOtherResponse(response, out status); else result = HandleBadResponse(ex.ToString(), out status); } catch (Exception ex) { result = HandleBadResponse(ex.ToString(), out status); } } // ... 

As you can see, the two try statements are different, but the two sets of catch statements are the same. I tried to figure out how I could not repeat myself here, but I really did not think that it would not be much slower or just awful to watch. I wonder if anyone has any ideas.

+4
source share
3 answers

One way is to write a "safe" call method and pass func to it:

 public T SafeInvocation(Func<T> myMethod) { T result = default(T); try { // Invoke method result = myMethod(); } catch { // Do your common catch here } return result; } 

Create an extra overload for Action <T> so you don't need to have a return type. You can then call it elsewhere, passing methods to your method as arguments (Inception?):

 SafeInvocation(() => { if (postXml != null) using (StreamWriter writer = new StreamWriter(req.GetRequestStream())) writer.Write(postXml.ToString()); } 
+4
source

You can pass Action to a function that handles exceptions:

 private void HandleErrorsFor(Action action) { try { action(); } catch (Exception ex) { //repeated exception handling... { } //... public void DoSomething() { HandleErrorsFor(() => { //try block #1 }); HandleErrorsFor(() => { //try block #2 }); } 

This is a little easier to read and avoids re-code.

0
source

You can do something with delegates and cover both try and catch blocks:

  static class Program { delegate void CodeBlock(); internal delegate void ExceptionCatcher(Exception ex); private static void Main() { CodeBlock b = () => { Console.WriteLine("HELLO WORLD"); }; CodeBlock error = () => { throw new Exception("Exception thrown"); }; ExceptionCatcher silence = exception => { }; ExceptionCatcher e = exception => { var currentColor = Console.BackgroundColor; Console.BackgroundColor = ConsoleColor.Red; Console.WriteLine(exception.Message); Console.BackgroundColor = currentColor; }; DRYRunner(b, e); DRYRunner(error , e); DRYRunner(error , silence); Console.ReadLine(); } static void DRYRunner (CodeBlock block, ExceptionCatcher catcher) { try { block.Invoke(); } catch (Exception ex) { catcher(ex); } } } 

edit: expanding this, we can create a class that will help contain and associate blocks of code with their possible exceptions and handlers. You can even create a class of common exception handlers and refer to them accordingly by mixing them with ad-hoc handlers:

  class ExceptionHandledDelegate { public delegate void CodeBlock(); public delegate void ExceptionCatcher(Exception ex); public Dictionary<Type, ExceptionCatcher> ExceptionHandlers; public CodeBlock codeBlock { get; set; } public void Run() { try { codeBlock.Invoke(); } catch (Exception ex) { var mn = ex.GetType(); if (ExceptionHandlers.Keys.Contains(mn)) { ExceptionHandlers[mn](ex); } else throw; } } } class CommonHandlers { public static void ArgumentHandler(Exception ex) { Console.WriteLine("Handling an argument exception"); } public static void DivZeroHandler(Exception ex) { Console.WriteLine("Please don't divide by zero. It upsets the universe."); } } static class Program { private static void Main() { var ehd = new ExceptionHandledDelegate { codeBlock = () => { throw new ArgumentException("An argument exception has been thrown"); }, ExceptionHandlers = new Dictionary<Type, ExceptionHandledDelegate.ExceptionCatcher> { {typeof (ArgumentException), CommonHandlers.ArgumentHandler}, {typeof (DivideByZeroException ),CommonHandlers.DivZeroHandler}, {typeof (Exception), exception => Console.WriteLine("An exception has been thrown")} } }; ehd.Run(); ehd.codeBlock = () => { throw new Exception("An exception has been thrown"); }; ehd.Run(); ehd.codeBlock = () =>{var denom = 0; Console.WriteLine(100 / denom);}; ehd.Run(); Console.ReadLine(); } } 
0
source

Source: https://habr.com/ru/post/1488374/


All Articles