The below method iterates through a Try-Catch until a valid object is returned by the statement driver.FindElement(By.Id(elementId)). If the element it is searching for doesn't exist yet (i.e. if the page is still loading for example) then an exception is thrown.
public static IWebElement AwaitElementLoadById(IWebDriver driver, string elementId)
{
bool result = false;
while (!result)
{
try
{
return driver.FindElement(By.Id(elementId));
}
catch (Exception)
{
result = false;
}
}
return null;
}
This works fine and as expected, however I remember reading a while back that Try-Catch statements should not be used to process/drive logic and only used for the desired purpose of handling exceptions.
My question then is, is there a more acceptable way of processing this kind of scenario without using a Try Catch to actually drive the logic.
Caveat: I know that this could potentially cause an infinite loop. In my working example I have a timeout on this method but for the sake of simplicity I have excluded from this snippet.
So the below worked for me in the end:
public static IWebElement AwaitElementLoadByPath(IWebDriver driver, string elementPath, int timoutDuration)
{
bool result = false;
DateTime starttime = DateTime.Now;
while ((!result) && (starttime.AddMilliseconds(timoutDuration) > DateTime.Now))
{
IWebElement returnValue = driver.FindElements(By.XPath(elementPath)).FirstOrDefault();
if (returnValue != null)
{
return returnValue;
}
}
return null;
}
Related
I'm writing a code to create a new object with key metadata being provided by a user input form. I'm wondering if there's a way to return the object (q) in the try block and not at the end of the method?
Here's my current code with some notes about how I want it all to look:
public NewSearchQuery GetEntry()
{
//pull all input field information and store ready for validation
string name = Convert.ToString(Companies.SelectedItem);
string location = String.Concat(Convert.ToString(Property.Text), " ", Convert.ToString(SearchLocation.Text).ToLower());
string searchtype = Convert.ToString(Search.SelectedItem);
var q = new NewSearchQuery();
//check all required input fields are filled in
if (String.IsNullOrEmpty(name) || String.IsNullOrEmpty(location) || String.IsNullOrEmpty(searchtype))
{
MessageBox.Show("Please ensure you have filled in all the required fields (*) before proceeding", "Insufficient Information");
this.ShowDialog();
}
else
{
try
{
q.GetFormData(name, location, searchtype, Paid.Checked); //replace this with a constructor for var q
q.Contract = ThisAddIn.GetContract(q.Name);
q.CreateIdNum();
q.CreateFilePath(q.Contract, q.RefNum);
q.CalculateFees();
}
catch (Exception d)
{
MessageBox.Show(Convert.ToString(d)); //return null if the try fails
}
}
return q; //relocate this to the try block
}
I want to make these changes because I suspect that returning the q value irrespective of the process working or not is causing my winform to error out it if try to exit it prematurely.
Is there a way I can get around the inevitable 'not all code paths return a value' error?
You can rewrite your method as follows:
public NewSearchQuery GetEntry()
{
//pull all input field information and store ready for validation
string name = Convert.ToString(Companies.SelectedItem);
string location = String.Concat(Convert.ToString(Property.Text), " ", Convert.ToString(SearchLocation.Text).ToLower());
string searchtype = Convert.ToString(Search.SelectedItem);
//check all required input fields are filled in
if (String.IsNullOrEmpty(name) || String.IsNullOrEmpty(location) || String.IsNullOrEmpty(searchtype))
{
MessageBox.Show("Please ensure you have filled in all the required fields (*) before proceeding", "Insufficient Information");
this.ShowDialog();
return null;
}
try
{
var q = new NewSearchQuery();
q.GetFormData(name, location, searchtype, Paid.Checked); //replace this with a constructor for var q
q.Contract = ThisAddIn.GetContract(q.Name);
q.CreateIdNum();
q.CreateFilePath(q.Contract, q.RefNum);
q.CalculateFees();
return q;
}
catch (Exception d)
{
MessageBox.Show(Convert.ToString(d)); //return null if the try fails
return null;
}
}
Now all code paths return a value. I omitted the else block, because if you leave the method inside the if block. This means, that the code following the if block is never executed when your condition is true, as it would be with the else block. The advantage of this is that you don't have so much nested bracings, which makes the code easier to understand.
Be sure to check whether the return value is not null, otherwise you might have a NullReferenceException.
Yes,
Write a return statement within every single block.
if(something)
{
return value;
}
else
{
try
{
return value;
}
catch
{
return value;
}
}
In c#, can I write something like this :
if (
(
try {
...
return true;
}
catch (Exception ex)
{
return false;
}
) == true
)
{
...
}
without having to move all my try/catch block inside a new function
-- edit --
OK. I complete my question. (and maybe answer it a bit).
What is supposed to be in the try/catch is a kind of XmlDocument.TryLoad(stream) (like there's a int.tryParse(string)).
I'll need it only once so that's why I'd wanted to avoid making an extra func.
So my code would be something like
try {
new XmlDocument().Load(foo);
return true;
}
catch (Exception ex)
{
return false;
}
I just want to know if it goes wrong. I don't care the reason (stream empty, bad encoding).
There are a lot of interesting answers but I think what's the more appropriate for me is to create a extension method for xmlDocument. It will be way cleaner (and reusable and easier to read) than trying to force an anonymous method in my statement
You can't use that exact syntax, no. You could write:
Func<bool> func = () =>
{
// Code in here
};
if (func())
{
...
}
... but personally I'd extract it into a separate method. It's likely to be considerably more readable - and potentially easier to test, too.
Not that I'd recommend catching exceptions like this either, but:
public static bool Try(Action action)
{
try
{
action();
return true;
}
catch (Exception)
{
return false;
}
}
Example usages
int x;
int a = 0;
int b = 1;
if (Try(() => x = a/b))
{
}
if (Try(OtherMethod))
{
}
if (Try(OtherMethod(1,2)))
{
}
if (((Func<bool>)(() =>
{
// Multi-statement evaluation
DateTime dt = DateTime.UtcNow;
if (dt.Hour <= 12)
return true;
else
return false;
}))())
{
Console.WriteLine("Early");
}
else
{
Console.WriteLine("Late");
}
From C# Language Specification 5.0 (8.7.1):
The if statement selects a statement for execution based on the value
of a boolean expression.
But your code:
(
try { return true; }
catch (Exception ex) { return false; }
) == true
Is not a boolean expression but a statement.
I like using implicit typing for almost everything because it's clean and simple. However, when I need to wrap a try...catch block around a single statement, I have to break the implicit typing in order to ensure the variable has a defined value. Here's a contrived hypothetical example:
var s = "abc";
// I want to avoid explicit typing here
IQueryable<ABC> result = null;
try {
result = GetData();
} catch (Exception ex) { }
if (result != null)
return result.Single().MyProperty;
else
return 0;
Is there a way I can call GetData() with exception handling, but without having to explicitly define the type of the result variable? Something like GetData().NullOnException()?
This is a common problem. I recommend that you just stick with your existing solution.
If you really want an alternative, here it is:
static T NullOnException<T>(Func<T> producer) where T : class {
try { return producer(); } catch { return null; } //please modify the catch!
}
//now call it
var result = NullOnException(() => GetData());
Please modify this to log the exception or restrict the catch to a concrete type. I do not endorse swallowing all exceptions.
As this answer is being read a lot I want to point out that this implementation is just of demo-quality. In production code you probably should incorporate the suggestions given in the comments. Write yourself a robust, well-designed helper function that will serve you well for years.
Just put your code inside the try:
var s = "abc";
// I want to avoid explicit typing here
try {
var result = GetData();
if (result != null)
return result.Single().MyProperty;
else
return 0;
} catch (Exception ex) { }
I came to a similar solution as #usr, but with slightly different semantics:
T LiftScope<T>(Func<T> ScopedFunction)
{
T result = ScopedFunction();
return result;
}
The purpose of LiftScope is to carry an internal variable out to the caller without compromising implicit typing. This could be used to solve the original problem, except that the try...catch would actually be embedded in the call.
try...catch
var result =
LiftScope(() => {
try { return producer(); } catch { return null; }
});
Now the caller is able to be responsible for exception handling. Furthermore, this can be used generically in a handful of similar use-cases where you have very short-lived scopes.
if
var result =
LiftScope(() => {
if (a == b)
return GetData(true);
else if (b == c)
return GetData(false);
else
return GetData(true, 2);
});
This could also be solved with a ternary-style if statement.
using
var result =
LiftScope(() => {
using (var myContext = new MyDataContext())
{
return myContext.MyTable.Where(w => w.A == B).ToList();
}
});
I have a method that calls a SQLServer function to perform a free text search against a table. That function will occasionally on the first call result in a SQLException: "Word breaking timed out for the full-text query string". So typically I want to retry that request because it will succeed on subsequent requests. What is good style for structuring the retry logic. At the moment I have the following:
var retryCount = 0;
var results = new List<UserSummaryDto>();
using (var ctx = new UsersDataContext(ConfigurationManager.ConnectionStrings[CONNECTION_STRING_KEY].ConnectionString))
{
for (; ; )
{
try
{
results = ctx.SearchPhoneList(value, maxRows)
.Select(user => user.ToDto())
.ToList();
break;
}
catch (SqlException)
{
retryCount++;
if (retryCount > MAX_RETRY) throw;
}
}
}
return results;
I'd change the exception handling to only retry on certain errors:
1204, 1205 deadlocks
-2 timeout
-1 connection broken
These are the basic "retryable" errors
catch (SqlException ex)
{
if !(ex.Number == 1205 || ex.Number == 1204 || ... )
{
throw
}
retryCount++;
if (retryCount > MAX_RETRY) throw;
}
Edit, I clean forgot about waits so you don't hammer the SQL box:
Add a 500 ms wait on deadlock
Add a 5 sec delay on timeout
Edit 2:
I'm a Developer DBA, don't do much C#.
My answer was to correct exception processing for the calls...
Thanks for all the feedback. I'm answering this myself so I can incorporate elements from the answers given. Please let me know if I've missed something. My method becomes:
var results = new List<UserSummaryDto>();
Retry<UsersDataContext>(ctx => results = ctx.SearchPhoneList(value, maxRows)
.Select(user => user.ToDto())
.ToList());
return results;
And I've refactored the original method for reuse. Still lots of levels of nesting. It also relies on there being a default constructor for the data context which may be too restrictive. #Martin, I considered including your PreserveStackTrace method but in this case I don't think it really adds enough value - good to know for future reference thanks:
private const int MAX_RETRY = 2;
private const double LONG_WAIT_SECONDS = 5;
private const double SHORT_WAIT_SECONDS = 0.5;
private static readonly TimeSpan longWait = TimeSpan.FromSeconds(LONG_WAIT_SECONDS);
private static readonly TimeSpan shortWait = TimeSpan.FromSeconds(SHORT_WAIT_SECONDS);
private enum RetryableSqlErrors
{
Timeout = -2,
NoLock = 1204,
Deadlock = 1205,
WordbreakerTimeout = 30053,
}
private void Retry<T>(Action<T> retryAction) where T : DataContext, new()
{
var retryCount = 0;
using (var ctx = new T())
{
for (;;)
{
try
{
retryAction(ctx);
break;
}
catch (SqlException ex)
when (ex.Number == (int) RetryableSqlErrors.Timeout &&
retryCount < MAX_RETRY)
{
Thread.Sleep(longWait);
}
catch (SqlException ex)
when (Enum.IsDefined(typeof(RetryableSqlErrors), ex.Number) &&
retryCount < MAX_RETRY)
{
Thread.Sleep(shortWait);
}
retryCount++;
}
}
}
My enum of retryables for sql looks like this:
SqlConnectionBroken = -1,
SqlTimeout = -2,
SqlOutOfMemory = 701,
SqlOutOfLocks = 1204,
SqlDeadlockVictim = 1205,
SqlLockRequestTimeout = 1222,
SqlTimeoutWaitingForMemoryResource = 8645,
SqlLowMemoryCondition = 8651,
SqlWordbreakerTimeout = 30053
It's not good style, but sometimes you have to do it, because you simply can't change existing code and have to deal with it.
I am using the following generic method for this scenario. Note the PreserveStackTrace() method, which can sometimes be very helpful in a re-throw scenario.
public static void RetryBeforeThrow<T>(Action action, int retries, int timeout) where T : Exception
{
if (action == null)
throw new ArgumentNullException("action", string.Format("Argument '{0}' cannot be null.", "action"));
int tries = 1;
do
{
try
{
action();
return;
}
catch (T ex)
{
if (retries <= 0)
{
PreserveStackTrace(ex);
throw;
}
Thread.Sleep(timeout);
}
}
while (tries++ < retries);
}
/// <summary>
/// Sets a flag on an <see cref="T:System.Exception"/> so that all the stack trace information is preserved
/// when the exception is re-thrown.
/// </summary>
/// <remarks>This is useful because "throw" removes information, such as the original stack frame.</remarks>
/// <see href="http://weblogs.asp.net/fmarguerie/archive/2008/01/02/rethrowing-exceptions-and-preserving-the-full-call-stack-trace.aspx"/>
public static void PreserveStackTrace(Exception ex)
{
MethodInfo preserveStackTrace = typeof(Exception).GetMethod("InternalPreserveStackTrace", BindingFlags.Instance | BindingFlags.NonPublic);
preserveStackTrace.Invoke(ex, null);
}
You would call it like that:
RetryBeforeThrow<SqlException>(() => MethodWhichFails(), 3, 100);
There is no good style for doing something like this. You'd be better off figuring out why the request fails the first time but succeeds the second time.
It seems possible that Sql Server has to initially compile an execution plan and then execute the query. So the first call fails because the combined times exceed your timeout property, and succeeds the second time because the execution plan is already compiled and saved.
I don't know how UsersDataContext works, but it may be the case that you have the option to Prepare the query before actually executing it.
Real Answer: If I had to do this, I would retry just once and not again, like this:
var results = new List<UserSummaryDto>();
using (var ctx = new
UsersDataContext(ConfigurationManager.ConnectionStrings[CONNECTION_STRING_KEY].ConnectionString))
{
try
{
results = ctx.SearchPhoneList(value, maxRows)
.Select(user => user.ToDto())
.ToList();
break;
}
catch (SqlException)
{
try
{
results = ctx.SearchPhoneList(value, maxRows)
.Select(user => user.ToDto())
.ToList();
break;
}
catch (SqlException)
{
// set return value, or indicate failure to user however
}
}
}
}
return results;
While I might trust you to not abuse the retry process, you'd be tempting your successor to increase the retry count as a quick fix.
I think annotating a method with an aspect specifying the retry count would result in more structured code, although it needs some infrastructure coding.
You can simply use SqlConnectionStringBuilder properties to sql connection retry.
var conBuilder = new SqlConnectionStringBuilder("Server=.;Database=xxxx;Trusted_Connection=True;MultipleActiveResultSets=true");
conBuilder.ConnectTimeout = 90;
conBuilder.ConnectRetryInterval = 15;
conBuilder.ConnectRetryCount = 6;
Note:- Required .Net 4.5 or later.
Pull the relevant code out into its own method, then use recursion.
Pseudo-code:
try
{
doDatabaseCall();
}
catch (exception e)
{
//Check exception object to confirm its the error you've been experiencing as opposed to the server being offline.
doDatabaseCall();
}
In Delphi I could do something like this:
try
if not DoSomething then
Exit;
if not DoSomething2 then
Exit;
if not DoSomething3 then
Exit;
finally
DoSomethingElse;
end;
In other means if method DoSomething results false then the program flow is transffered to the finally block and DoSomething2 and DoSomething3 are not executed.
How to achieve such behaviour in C#?
Thanks in advance.
Edit1:
The below example doesn't compile in VS 2008
Edit2: I am sorry I was to fast and forget the return statement;
XElement OrderStatus(q_order_status Request)
{
XElement Response;
try
{
if (DoSomething() != 0 )
{
return;
}
}
catch(Exception e)
{
// catch some errors and eventually pass the e.Message to the Response
}
finally
{
Response = new XElement("SomeTag", "SomeResponse");
}
return Response;
}
Edit3:
After testing it seems that the easiest way to achieve this is to throw an exception if the result of DoSomething1 is false. I can throw my own execption, write a specific message and pass it to the finally clause.
You really shouldn't be using exception handling constructs for flow control. That said, Exit is comparable to return in C#. As the MSDN Documentation about the [return keyword][1] says:
If the return statement is inside a try block, the finally block, if one exists, will be executed before control returns to the calling method.
In general a finally-block will almost always execute if the corresponding try-block has been reached. There are a few rare situations where it is impossible to guarantee that the finally-block executes, but they are all fatal errors, upon which programs should likely immediately crash.
How your code would look in C#:
try
{
if (!DoSomething())
return;
if (!DoSomething2())
return;
if (!DoSomething3())
return;
}
finally
{
DoSomethingElse();
}
But again, don't do this. try and finally are intended for handling exceptions, not for normal flow control.
Reply to your edit:
In your code return doesn't compile because the return type of the method is XElement and return by itself can only be used when the return type is void. You could use return new XElement("SomeTag", "SomeResponse");, as that is what the finally would be doing anyway, or you could assign Response earlier and do return Response;.
Note though that while the finally always executes, the return Response; that comes after it doesn't execute if the reason went into the finally-block is because you did a return inside the try-block.
Answer to updated question:
The reason you're having trouble doing this in an elegant way, is because you seem to be using a combination of return values and exceptions. You should consider manually raising an exception instead of using return values if the sitation is, well, exceptional.
Assuming there is a good reason for the return values however, I'm thinking it might be clearer to go without a finally block altogether, and to include a return at the end of the try block and also in your catch block. That would save you from passing the exception message in a messy way.
I can't really say what the best solution would be, since your code snippet does not show what Response would be if DoSomething() returns a non-zero value.
Original answer:
It depends a little on what you're trying to accomplish. Are exceptions actually being thrown in any of the methods? Otherwise there is no good reason to use a try-finally pattern. This would be equivalent (though maybe not advisable for readability):
bool doneEverything = DoSomething() && DoSomething2() && DoSomething3();
DoSomethingElse();
If there are exceptions being thrown, and handled at a higher level, I'd recommend isolating this code in a separate method, so you can use a return statement*.
void DoStuff()
{
try
{
if (!DoSomething())
return;
if (!DoSomething2())
return;
if (!DoSomething3())
return;
}
finally
{
DoSomethingElse();
}
}
To answer your question about when the finally code block is executed: it is always executed, unless the executing thread terminates prematurely.
*: Some restructuring is recommended, because there is no equivalent of the Delphi Exit. The break statement comes closest, but it can only be used in loop constructs or switch blocks. To mimic Exit behavior, you would need goto and a label. We wouldn't want that, now would we? :)
Why not make the three try-lines a common if/else block? Instead of exit, call the DoSomethingElse. Like so:
if (DoSomething() == false)
{
DoSomethingElse();
}
else if (DoSomething2() == false)
{
DoSomethingElse();
}
else if (DoSomething3() == false)
{
DoSomethingElse();
}
I would like to say that "C# is not Delphi", but that would be a bit arrogant.
In C#, finally is executed as well when return is called inside the try statement.
bool doSomething = false;
bool doSomething2 = true;
try
{
if( !doSomething )
{
Console.WriteLine ("not dosomething");
return;
}
if( !doSomething2 )
{
Console.WriteLine ("not dosomething 2");
return;
}
}
finally
{
Console.WriteLine ("In finally");
}
What about switch case of course If you don't mean the finally in c# by saying finally block. default case is the finally block then and you can also find flow control example and here at msdn : Flow Control (C# vs. Java)
static void Main(string[] args)
{
switch (args[0])
{
case "copy":
//...
break;
case "move":
//...
goto case "delete";
case "del":
case "remove":
case "delete":
//...
break;
default:
//...
break;
}
}
In this sort of situation, understanding the question as dealing exclusively with the non-exception handling case, I would refactor the contents of the try into a private helper method, like this
void BranchOnContext()
{
if (!DoSomething())
return;
if (!DoSomething2())
return;
// last one will drop out and return anyway
DoSomething3();
}
void DoStuff()
{
BranchOnContext(); // Assumed not to throw
DoSomethingElse(); // Always the next thing to be executed
}
EDIT -- tracking the changed requirement
void DoStuff()
{
string message = string.Empty;
try {
BranchOnContext();
} catch (MyExpectedException me) { // only catch exceptions I'm prepared to handle
message = me.Message;
}
DoSomethingElse(message); // Always the next thing to be executed
}
Taking another crack at this with the updated info:
I want DoSomethingElse to be executed
always and I want it to include
message from possible exception
If any of the DoSomething's return 0, null is returned. If not, the generic message is created. If there was an exception, it is caught and a message with its info is returned. How about this?
XElement OrderStatus(q_order_status Request)
{
try
{
if (DoSomething() != 0 )
{
return null;
}
else
{
return new XElement("SomeTag", "SomeResponse");
}
}
catch(Exception e)
{
// catch some errors and eventually pass the e.Message to the Response
return new XElement(e.tag, e.response);
}
}
Im still struggling with how to, in a good way, put finally into this.
I find it quite similar in behavior to the Delphi's one which I have shown on the beginning. I am interested in your comments. Response is dependent on the DoSomethings result.
XElement OrderStatus(q_order_status Request)
{
XElement Response;
int result = 0;
string Message = "";
try
{
result = DoSomething1();
if (result != 0)
{
throw new DoSomethingException("DoSomething1 has failed!");
}
result = DoSomething2();
if (result != 0)
{
throw new DoSomethingException("DoSomething2 has failed!");
}
result = DoSomething3();
if (result != 0)
{
throw new DoSomethingException("DoSomething3 has failed!");
}
Message = "All tests has been passed.";
}
catch(DoSomethingException e)
{
Message = e.Message;
}
catch(Exception e)
{
Message = e.Message;
}
finally
{
Response = new XElement("SomeTag", Message);
}
return Response;
}
What do you think?
void funcA()
{
if (!DoSomething())
return;
if (!DoSomething2())
return;
if (!DoSomething3())
return;
}
void funcB()
{
funcA();
DoSomethingElse;
}
This appears to replicate the delphi:-
try
{
if(DoSomething())
if(DoSomething2())
DoSomething3();
}
finally
{
DoSomethingElse();
}
an alternate style (some people will hate this style, others will love it.):-
try
{
DoSomething() && DoSomething2() && DoSomething3();
}
finally
{
DoSomethingElse();
}
I get the impression you want some other behaviour though?
Goto version?
try
{
if (!DoSomething())
goto Exit;
if (!DoSomething2())
goto Exit;
if (!DoSomething3())
goto Exit;
Exit:;
}
finally
{
DoSomethingElse();
}
Note the irritating ; after the label, it seems a label must precede a statement.
Just had an epiphany:-
Func<bool>[] somethings = new Func<bool>[] {DoSomething, DoSomething2, DoSomething3};
try
{
foreach (Func<bool> something in somethings)
{
if (!something())
break;
}
}
finally
{
DoSomethingElse();
}