1

Follow up from question here: Cleanest way to write retry logic?

In the answer, a generic class to retry functions is defined and used as such:

Retry.Do(() => SomeFunctionThatCanFail(), TimeSpan.FromSeconds(1));

How would you implement a generic retry, where the constructor can throw also?

So I don't just want to retry:

   SomeFunctionThatCanFail() 

I want to retry the following block in a generic fashion:

   SomeClass sc = new SomeClass();
   sc.SomeFunctionThatCanFail();
Community
  • 1
  • 1
Robben_Ford_Fan_boy
  • 8,494
  • 11
  • 64
  • 85
  • If you don't need to access `sc` later, you could do new `Retry.Do(() => new SomeClass().SomeFunctionThatCanFail(), TimeSpan.FromSeconds(1));` – Eric Phillips Dec 21 '16 at 21:01
  • 1
    "where Constructor Can Throw" sounds fishy to me. Yes constructor may throw but has to be something seriously wrong. Not something that might work on a 2nd try – Steve Dec 21 '16 at 21:10
  • What's wrong with putting the entire block into the lambda expression? – Mike Zboray Dec 21 '16 at 21:24
  • 1
    The supposition of the question is that the ctor can throw; presumably there is no way to *prevent* the ctor from throwing because if there was, you'd do it and then you wouldn't need to retry. But the additional supposition of the question is that *doing the same thing again will not throw*. So, you have a ctor that throws unpredictably. Don't put a bandaid on that code; delete it and write a ctor that behaves predictably. – Eric Lippert Dec 21 '16 at 21:25
  • 1
    @EricLippert I was actually going to link [Vexing exceptions](https://blogs.msdn.microsoft.com/ericlippert/2008/09/10/vexing-exceptions/), in my post lol.... – Erik Philips Dec 21 '16 at 21:34
  • 1
    Exponential backoff is a good retry strategy than simply trying x number of times. You can use a library like Polly to implement it. – utsavized Dec 21 '16 at 23:08

2 Answers2

3

where the constructor can throw also?

Generally this is a bad idea. I would recommend looking at the Factory Pattern:

public class SomeClass
{
  private SomeClass()
  {
  }

  public static SomeClass GetInstance()
  {
    // Throw Exception here, not in constructor
  }

  public void SomeFunctionThatCanFail()
  {
  }
}

Now you can do:

Retry.Do(() => 
  SomeClass.GetInstance().SomeFunctionThatCanFail(), 
  TimeSpan.FromSeconds(1));
Erik Philips
  • 53,428
  • 11
  • 128
  • 150
0

I did not realise I could put a block of code into the Lambda expression. This is exactly what I want:

Retry.Do(() => { using (DataBaseProxy db = new DataBaseProxy(dbList.Next())) { .DoSomething(); } }, new TimeSpan(0));
Robben_Ford_Fan_boy
  • 8,494
  • 11
  • 64
  • 85