Rethrow exception in for loop - c#

I want to create a method to retry some code with wait when exception occur. How can I get rid of that last exception?
public static T TryWithWait<T>(Func<T> func, int tries, TimeSpan exceptionSleep)
{
if (tries < 1)
throw new Exception("Tries amount cannot be < 1");
for (int i = 0; i < tries; i++)
{
try
{
return func.Invoke();
}
catch
{
if (i == (tries - 1))
throw;
else
Thread.Sleep(exceptionSleep);
}
}
throw new Exception("Code wouldn't compile without that");
}

You can use recursivity !
public static T TryWithWait<T>(Func<T> func, int tries, TimeSpan exceptionSleep, Exception innerException = null)
{
// You must to knows what exception was generated, I put it as InnerException
if (tries < 1) throw new Exception("Tries amount cannot be < 1", innerException);
try
{
return func.Invoke();
}
catch(Exception exception)
{
return TryWithWait(func, --tries, exceptionSleep, exception);
}
}

Related

Loop to repeat a method 3 times if condition fails

Im looking for a simple way, to repeat a method, when an element(selector) for example a button on a webpage cant be found.
My idea or my plan is, that:
If the selector can be found, the method is done
If the selector cant be found, it should repeat the "FindElement" method up to maximal 3 times
If the selector cant be found after the third try, it should give me an output message of the "NoSuchElementException e"
I tried different loops and i always end up having endless loops like in the code below.
public static void FindElement(IWebDriver webDriver, string selector)
{
int maxTries = 0;
try
{
webDriver.FindElement(By.XPath(selector));
Console.WriteLine("Element found.");
}
catch (NoSuchElementException e)
{
if (maxTries !> 3 )
{
Console.WriteLine("Element, not found. Retrying.");
maxTries++;
FindElement(webDriver, selector);
}
else
{
Console.WriteLine(e);
}
}
}
What a coincidence: Just a few days ago I wrote a short helper method to separate "retry logic" from "business logic".
private T Retry<T>(Func<T> action, int maxRetryCount, int waitMilliseconds,
Func<Exception, bool> retryCondition)
{
var retryCount = 0;
while (true)
{
try
{
// If the action was successful (no exception thrown),
// we can leave the method.
return action();
}
catch (Exception ex) when (retryCount < maxRetryCount && retryCondition(ex))
{
retryCount += 1;
Thread.Sleep(waitMilliseconds);
}
}
}
Which would be called as follows in your case:
var element = Retry(() => webDriver.FindElement(By.XPath(selector)),
2, 0,
ex => ex is NoSuchElementException);
Whenever the maximum number of retries is reached, the exception is not caught any more (the when condition fails) and can be caught by your regular exception handling logic instead.
Since you are trying to automate a web browser, you might consider passing something else than 0 as waitMilliseconds, to give the browser time to render the elements that are still missing.
Why don't you put the maxTry outside of your function?
int maxTry=3;
string errorMessage="";
for(int i=0;i<maxTry;i++)
{
try
{
FindElement(webDriver,selector)
errorMessage="";
break;
}
catch (NoSuchElementException e)
{
errorMessage=e;
}
}
if(errorMessage!="")
{
Console.WriteLine(e);
}
else
{
Console.WriteLine("Element found.");
}
For recursion, you should pass the amount of remaining iterations to the function, and decrement it for each iteration.
public static void FindElement(IWebDriver webDriver, string selector, int iterations = 3)
{
iterations--;
if (iterations < 0)
{
Console.WriteLine("Max iterations passed, exiting")
return;
}
try
{
webDriver.FindElement(By.XPath(selector));
Console.WriteLine("Element found.");
}
catch (NoSuchElementException e)
{
Console.WriteLine("Element not found. Retrying.");
FindElement(webDriver, selector, iterations);
}
}

try catch over IEnumerable is not working as expected [duplicate]

This question already has answers here:
Why does this string extension method not throw an exception?
(3 answers)
Closed 7 years ago.
I just had a case with a method using yield return not throwing an ArgumentException which I expected. I have reconstructed the case with the simpliest possible classes here:
class Program
{
static void Main(string[] args)
{
try
{
var listA = FooA(count: 0);
Console.WriteLine("A did not throw exception!");
}
catch (ArgumentException)
{
Console.WriteLine("A threw exception!");
}
try
{
var listB = FooB(count: 0);
Console.WriteLine("B did not throw exception!");
}
catch (ArgumentException)
{
Console.WriteLine("B threw exception!");
}
Console.ReadLine();
}
private static IEnumerable<int> FooA(int count)
{
if(count == 0)
throw new ArgumentException("Count must be above 0");
var list = new List<int>();
for (var i = 0; i < count; i++)
{
list.Add(i);
}
return list;
}
private static IEnumerable<int> FooB(int count)
{
if (count == 0)
throw new ArgumentException("Count must be above 0");
for (var i = 0; i < count; i++)
{
yield return i;
}
}
}
Output:
A threw exception!
B did not throw exception!
Can some one please explain to me why FooB does not throw an exception while FooA does?
It's because FooB is never even evaluated.
When you call a method, that method is called immediately. When you use yield and return an enumerable, that method is only called when something needs to use the value returned, and only a single item at a time; this is the benefit of yielding.
So, if you add something that uses the value
try
{
var listB = FooB(count: 0);
Console.WriteLine(listB.First()); // use the IEnumerable returned
Console.WriteLine("B did not throw exception!");
}
catch (ArgumentException)
{
Console.WriteLine("B threw exception!");
}
You will see your expected result.

Yield return and exception handling [duplicate]

This question already has answers here:
Why does this string extension method not throw an exception?
(3 answers)
Closed 7 years ago.
I just had a case with a method using yield return not throwing an ArgumentException which I expected. I have reconstructed the case with the simpliest possible classes here:
class Program
{
static void Main(string[] args)
{
try
{
var listA = FooA(count: 0);
Console.WriteLine("A did not throw exception!");
}
catch (ArgumentException)
{
Console.WriteLine("A threw exception!");
}
try
{
var listB = FooB(count: 0);
Console.WriteLine("B did not throw exception!");
}
catch (ArgumentException)
{
Console.WriteLine("B threw exception!");
}
Console.ReadLine();
}
private static IEnumerable<int> FooA(int count)
{
if(count == 0)
throw new ArgumentException("Count must be above 0");
var list = new List<int>();
for (var i = 0; i < count; i++)
{
list.Add(i);
}
return list;
}
private static IEnumerable<int> FooB(int count)
{
if (count == 0)
throw new ArgumentException("Count must be above 0");
for (var i = 0; i < count; i++)
{
yield return i;
}
}
}
Output:
A threw exception!
B did not throw exception!
Can some one please explain to me why FooB does not throw an exception while FooA does?
It's because FooB is never even evaluated.
When you call a method, that method is called immediately. When you use yield and return an enumerable, that method is only called when something needs to use the value returned, and only a single item at a time; this is the benefit of yielding.
So, if you add something that uses the value
try
{
var listB = FooB(count: 0);
Console.WriteLine(listB.First()); // use the IEnumerable returned
Console.WriteLine("B did not throw exception!");
}
catch (ArgumentException)
{
Console.WriteLine("B threw exception!");
}
You will see your expected result.

Handling Exceptions - return to to error after catch

i would like to handle an exception in a particular way.
try
{
for (int i = 0; i < rows.Count; i++)
{
doSomething();
}
}
catch (Exception e)
{
return false;
}
im running throw an ienum and try to find an elem with doSomething() method.
the thing is that this method throws an exception when he can't find it, but i need to make sure that i can't find the element in the whole enum.
So this is the thing... i would like to know if there is a way inside the catch to do this:
if(i<rows.Count)
continueFor;
Ty in advance.
Put the try catch in the for loop
for (int i = 0; i < rows.Count; i++)
{
try{
doSomething();
}
catch(Exception ex){
// do something else
}
}
This way you can reference i. Alternatively set a property to be i and then in your catch you will know what (i) is.
Int32 lastNumber = 0;
try{
for (int i = 0; i < rows.Count; i++)
{
lastNumber = i;
doSomething();
}
}
catch(Exception ex){
// do something else with lastNumber
}
You should instead return a boolean from your DoSomething method and test the value returned inside the loop. If you really need a try/catch block, put it inside the method, especially since you are not using the exception raised in your catch.
bool returnValue;
for (int i = 0; i < rows.Count; i++)
{
if(doSomething())
returnValue = true;
}
return returnValue;

How to check that i > 0 with try... catch?

I want to check that a variable (e.g "totalSum" is bigger than 0) with try catch, and if it isn't
I want the program to cancel and write out a message to the user.
Following code is by obvious reasons not possible to compile, but hopefully you see what I want with it:
while (true)
{
try
{
totalSum > 0;
break;
}
catch
{
Console.WriteLine("Total sum is too small.");
End program
}
}
Is it possible to do this with try...catch and if so, how to do it?
A try/catch block can do this:
try
{
if (totalSum < 0)
throw new ApplicationException();
}
catch (Exception ex)
{
Console.WriteLine("Total sum is too small");
Environment.Exit(1);
}
But a simple if statement can do this with a lot less work:
if (totalSum < 0)
{
Console.WriteLine("Total sum is too small");
Environment.Exit(1);
}
You could do this, though I don't recommend it:
try
{
if (totalSum < 0)
throw new ArgumentOutOfRangeException("totalSum", "Total sum is too small.");
}
catch (ArgumentOutOfRangeException ex)
{
Console.WriteLine(ex.Message);
}
you can throw an exception
if (totalSum < 0)
{
throw new InvalidArgumentException("totalSum");
}
There is not much reason to use try catch.
You can do
try {
if(!(totalSum > 0)) throw new Exception();
} catch {
Console.WriteLine("Total sum is too small.");
}
But really, no reason to do so - why do you have to use try..catch?
There is no reason to use a try/catch block here. Use exceptions for exceptional circumstances only. In your case, just use if and else:
if (totalSum > 0)
{
// Good! Do something here
}
else
{
// Bad! Tell the user
Console.WriteLine("Bad user!");
}
Or, if you'd like to loop:
int totalSum = 0;
while (totalSum <= 0)
{
totalSum = GetSum();
if (totalSum <= 0)
Console.WriteLine("Too small!");
}

Categories

Resources