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!");
}
Related
My program is simply a square root
I take an integer from the user in a TextBox and give the result using the function Math.Sqrt
in the other TextBox.
What I am trying to do now is to show a MessageBox using try/catch exceptions that tells the user
he can't use a negative number I used if statement but did not show the MessageBox just getting NaN value, please if anyone could help
int num1;
try
{
num1 = System.Convert.ToInt32((textBox1.Text));
textBox2.Text = System.Convert.ToString(Math.Sqrt(num1));
}
catch (FormatException)
{
MessageBox.Show("Data type is wrong");
}
catch (Exception)
{
num1 = 0;
if (num1 < 0)
MessageBox.Show("Number must be positive");
}
Usually, exceptions are used to manage rare events. Manage exceptions it's costly. In your case, maybe normal a typo error or even a negative number. It's better manage as a normal thing.
int num1;
if (int.TryParse(textBox1.Text, out num1) && num1 >= 0)
{
textBox2.Text = Convert.ToString(Math.Sqrt(num1));
}
else
{
MessageBox.Show("You must enter a positive number");
}
If you need use try/catch:
try
{
int num1 = int.Parse(textBox1.Text);
if (num1 >= 0)
{
textBox2.Text = Convert.ToString(Math.Sqrt(num1));
}
else
{
MessageBox.Show("You must enter a positive number");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Check the documentation for Math.Sqrt(). This function doesn't throw an exception when number is negative. This is first reason why the code for catch(Exception){} is not being executed.
Secondly you are setting
num1 = 0;
and then next checking
if(num<0){} // This will always be false
Anyways I recommend to check the num1 value before you calculate the root
int num1;
try
{
num1 = System.Convert.ToInt32((textBox1.Text));
if (num1 < 0)
MessageBox.Show("Number must be positive");
else
textBox2.Text = System.Convert.ToString(Math.Sqrt(num1));
}
catch (FormatException)
{
MessageBox.Show("Data type is wrong");
}
catch (Exception)
{
}
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);
}
}
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);
}
}
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;
The following code was a proof of concept for a message batching routine. Do I avoid goto like the plague and rewrite this code? Or do you think the goto is an expressive way to get this done?
If you'd rewrite please post some code...
var queue = new Queue<TraceItem>(this.batch);
while (this.connected)
{
byte[] buffer = null;
try
{
socket.Recv(out buffer);
}
catch
{
// ignore the exception we get when the socket is shut down from another thread
// the connected flag will be set to false and we'll break the loop
}
HaveAnotherMessage:
if (buffer != null)
{
try
{
var item = TraceItemSerializer.FromBytes(buffer);
if (item != null)
{
queue.Enqueue(item);
buffer = null;
if (queue.Count < this.batch && socket.Recv(out buffer, ZMQ.NOBLOCK))
{
goto HaveAnotherMessage;
}
}
}
catch (Exception ex)
{
this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
this.tracer.TraceException(TraceEventType.Error, 0, ex);
}
}
// queue processing code
}
Pretty much sums up my thoughts on "goto."
Goto is bad programming practice for many reasons. Chief among them is that there is almost never a reason for it. Someone posted a do..while loop, use that. Use a boolean to check if you should continue. Use a while loop. Goto's are for interpreted languages and a call back to assembler days (JMP anyone?). You're using a high level language for a reason. So that you and everyone else doesn't look at your code and get lost.
To keep this answer somewhat current I'd like to point out that a combination of goto and bracing errors caused a major SSL bug in iOS and OS X.
Replace the goto with a do-while, or simply a while loop if you don't want the "always run once" functionality you have right now.
var queue = new Queue<TraceItem>(this.batch);
while (this.connected)
{
byte[] buffer = null;
try
{
socket.Recv(out buffer);
}
catch
{
// ignore the exception we get when the socket is shut down from another thread
// the connected flag will be set to false and we'll break the loop
}
do {
if (buffer != null)
{
try
{
var item = TraceItemSerializer.FromBytes(buffer);
if (item != null)
{
queue.Enqueue(item);
buffer = null;
}
}
catch (Exception ex)
{
this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
this.tracer.TraceException(TraceEventType.Error, 0, ex);
}
}
} while(queue.Count < this.batch && socket.Recv(out buffer, ZMQ.NOBLOCK))
// queue processing code
}
It's so amazingly easy to rid yourself of GOTO in this situation it makes me cry:
var queue = new Queue<TraceItem>(this.batch);
while (this.connected)
{
byte[] buffer = null;
try
{
socket.Recv(out buffer);
}
catch
{
// ignore the exception we get when the socket is shut down from another thread
// the connected flag will be set to false and we'll break the loop
}
bool hasAnotherMessage = true
while(hasAnotherMessage)
{
hasAnotherMessage = false;
if (buffer != null)
{
try
{
var item = TraceItemSerializer.FromBytes(buffer);
if (item != null)
{
queue.Enqueue(item);
buffer = null;
if (queue.Count < this.batch && socket.Recv(out buffer, ZMQ.NOBLOCK))
{
hasAnotherMessage = true;
}
}
}
catch (Exception ex)
{
this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
this.tracer.TraceException(TraceEventType.Error, 0, ex);
}
}
}
// queue processing code
}
I guess the goto is SLIGHTLY more readable intuitively... But if you WANTED to avoid it I think all you'd have to do is throw the code in a while(true) loop, and then have a break statement at the end of the loop for a normal iteration. And the goto could be replaced with a continue statement.
Eventually you just learn to read and write loops and other control flow structures instead of using goto statements, at least in my experience.
Kind of related to Josh K post but I'm writing it here since comments doesn't allow code.
I can think of a good reason: While traversing some n-dimensional construct to find something. Example for n=3 //...
for (int i = 0; i < X; i++)
for (int j = 0; j < Y; j++)
for (int k = 0; k < Z; k++)
if ( array[i][j][k] == someValue )
{
//DO STUFF
goto ENDFOR; //Already found my value, let's get out
}
ENDFOR: ;
//MORE CODE HERE...
I know you can use "n" whiles and booleans to see if you should continue.. or you can create a function that maps that n-dimensional array to just one dimension and just use one while but i believe that the nested for its far more readable.
By the way I'm not saying we should all use gotos but in this specific situation i would do it the way i just mentioned.
You could refactor is to something like this.
while (queue.Count < this.batch && buffer != null)
{
try
{
var item = TraceItemSerializer.FromBytes(buffer);
buffer = null;
if (item != null)
{
queue.Enqueue(item);
socket.Recv(out buffer, ZMQ.NOBLOCK)
}
}
catch (Exception ex)
{
this.ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
this.tracer.TraceException(TraceEventType.Error, 0, ex);
}
}
Umm, I'm not really sure you want to goto out of a try block. I'm pretty sure that is not a safe thing to do, though I'm not 100% sure on that. That just doesn't look very safe...
Wrap the "HaveAnotherMessage" into a method that takes in the buffer and may call itself recursively. That would seem to be the easiest way to fix this.
I would avoid goto in this case, and refactor it. The method reads too long in my opinion.
I think your method is too big. It mixes different levels of abstraction, like error processing, message retrieval and message processing.
If you refactor it in different methods, the goto naturally goes away (note: I assume your main method is called Process):
...
private byte[] buffer;
private Queue<TraceItem> queue;
public void Process() {
queue = new Queue<TraceItem>(batch);
while (connected) {
ReceiveMessage();
TryProcessMessage();
}
}
private void ReceiveMessage() {
try {
socket.Recv(out buffer);
}
catch {
// ignore the exception we get when the socket is shut down from another thread
// the connected flag will be set to false and we'll break the processing
}
}
private void TryProcessMessage() {
try {
ProcessMessage();
}
catch (Exception ex) {
ProcessError(ex);
}
}
private void ProcessMessage() {
if (buffer == null) return;
var item = TraceItemSerializer.FromBytes(buffer);
if (item == null) return;
queue.Enqueue(item);
if (HasMoreData()) {
TryProcessMessage();
}
}
private bool HasMoreData() {
return queue.Count < batch && socket.Recv(out buffer, ZMQ.NOBLOCK);
}
private void ProcessError(Exception ex) {
ReceiverPerformanceCounter.IncrementDiagnosticExceptions();
tracer.TraceException(TraceEventType.Error, 0, ex);
}
...