Related to this question
Suppose I have a long method which I want to abort on certain conditions. What's the best way to do this? Here are two ways I can think of.
try
{
// if i is 0, we don't want to continue
int i = testi();
if(i == 0)
throw new StopException("stop")
// the rest of our code
}
catch(StopException stop)
{
// handle our stop exception
}
catch{
// everything else
}
Here's another
bool go = true
while(go)
{
// if i is 0, we don't want to continue
int i = testi();
if(i == 0)
{
go = false;
break;
}
// the rest of our code
}
Both of these seem clunky. Throwing an exception seems like overkill, and I don't actually want to loop anything so while is being misused. It seems to me there should be (and probably is) a more elegant way of doing this in C#?
RETURN!
Doy. I have actually used this lots of times, for some reason it just popped out of my head today. Thanks for indulging me in my stupidity
The standard way to interrupt a C# method is by simply using the return statement.
if method is void simply return, if not then return null or return 0 depends on the case.
definitely no need to throw and exception just instead of a return.
Just exit the method using the return statement.
void longMethod()
{
int i = testi();
if(i == 0)
return;
// Continue with method
}
Related
So I have a bit of C# code that looks like the below (simplified for the purpose of the question, any bugs are from me making these changes). This code can be called from multiple threads or contexts, in an asynchronous fashion. The whole purpose of this is to make sure that if a record already exists, it is used, and if it doesn't it gets created. May or may not be great design, but this works as expected.
var timeout = TimeSpan.FromMilliseconds(500);
bool lockTaken = false;
try
{
Monitor.TryEnter(m_lock, timeout, ref lockTaken); // m_lock declared statically above
if (lockTaken)
{
var myDBRecord = _DBContext.MyClass.SingleOrDefault(x => x.ForeignKeyId1 == ForeignKeyId1
&& x.ForeignKeyId2 == ForeignKeyId2);
if (myDBRecord == null)
{
myDBRecord = new MyClass
{
ForeignKeyId1 == ForeignKeyId1,
ForeignKeyId2 == ForeignKeyId2
// ...datapoints
};
_DBContext.MyClass.Add(myDBRecord);
_DBContext.SaveChanges();
}
}
else
{
throw new Exception("Can't get lock");
}
}
finally
{
if (lockTaken)
{
Monitor.Exit(m_lock);
}
}
The problem occurs if there are a lot of requests that come in, it can overwhelm the monitor, timing out if it has to wait too long. While the timeout for the lock can certainly be shorter, what is the preferred approach, if any, to addressing this type of a problem? Anything that would try to see if the monitor'd code needed to be entered would need to be part of that atomic operation.
I would suggest that you get rid of the monitor altogether and instead handle the duplicate key exception. You have to handle the condition where you are trying to enter a duplicate value anyway, why not do so directly?
I'm very new to Selenium so I'm looking for some insight on how to achieve this.
Essentially, I want my driver to wait for one of multiple elements to be visible. This is because the website can produce mixed results when using automation, so I want to treat this like it's "error handling" (if that makes sense).
Basically, if element a is visible first, do this. However, if element b is visible first, do that.
How would I be able to achieve this using the Selenium webdriver for C#? I read that combining the elements' XPath value by using "|" worked, however when I tried it with my application, I had no luck.
Any answers are greatly appreciated! Thank you in advance!
To me this is kind of tough because your elements could be displayed within a split second of each other. Wonder if you could put this in a case and break when you get one?
So what I was thinking was seeing if the element was present first.
public static bool IsElementPresent_byXpath(string xpath)
{
bool result;
try { result = Driver.FindElement(By.XPath(xpath)).Displayed; }
catch (NoSuchElementException) { return false; }
catch (StaleElementReferenceException) { return false; }
return result;
}
So if you do it this way, then you can write something like the below but my concern is that if the page is not changing, ele1, ele2 and ele3 could be invoked. So this code would need to be changed.
bool ele1 = Browser.IsElementPresent_byXpath("//[#id='1']");
bool ele2 = Browser.IsElementPresent_byXpath("//[#id='2']");
bool ele3 = Browser.IsElementPresent_byXpath("//[#id='3']");
if (ele1)
{
//do this
}
else if (ele2 || ele1 == false)
{
//do this
}
else if (ele3 || ele1 == false || ele2 == false)
{
//do this
}
I would go with Wait.Until, so that I can combine the benefits of waiting with set timeout for an event, and returning me matching locator, so I can base my logic on the result.
This is java code, but C# has equivalents.
Assuming I am waiting for either firstBy, secondBy or thirdBy:
By locatorOfElementThatIsPresent = new WebDriverWait(webDriver, timeoutInSeconds).<By>until(driver -> {
// findElements does not throw when element not found, so I skip try-catch
if (driver.findElements(firstBy).size() > 0) return firstBy;
if (driver.findElements(secondBy).size() > 0) return secondBy;
if (driver.findElemetns(thirdBy).size() > 0) return thirdBy;
return null; // neither found, so the method will be retried until timeout
});
I have a method that i have to call it from itself for multiple times in order to get a result and i want to know is Recursive call work as goto in this situation ?
Dummy Code:
public int DummyMethod()
{
string token;
int result = -1;
token = GetNewToken();
Stopwatch stopwatch = Stopwatch.StartNew();
while (result == -1)
{
if (stopwatch.Elapsed >= TimeSpan.FromSeconds(350)) {
//This is related to some logic as the token for the website
//expires after 350 seconds.
result = DummyMethod();
continue; //DO I NEED TO USE contunue ? or the recursive
//call broke the method (as if i used goto)
}
result = GetResultFromWebSite(token);
}
return result;
}
I think you have this all wrong and you definitely shouldn't be trying to figure out if your token has expired. This should be something the server tells you. If it comes via an exception you could do something like this:
public int DummyMethod(int retries = 0)
{
string token;
try
{
token = GetNewToken();
return GetResultFromWebSite(token);
}
catch (Exception e)
{
if (retries < 4) // or whatever max you want - you probably shouldn't hardcode it
{
return DummyMethod(++retries);
}
throw new Exception("Server ain't responding");
}
}
In a situation like this, it's often a good idea to have a maximum number of retries after which you will give up and show an error message.
You should instead use
return DummyMethod();
which is a tail call (the compiler can turn it into a goto).
This is a good illustration of one way the "single entry/single return" mantra fails.
However, I'm pretty sure you could just build this into the loop and avoid recursion:
public int DummyMethod()
{
Stopwatch stopwatch = Stopwatch.StartNew();
string token = GetNewToken();
int result;
do
{
if (stopwatch.Elapsed.TotalSeconds >= 350) {
token = GetNewToken();
stopwatch.Restart();
}
result = GetResultFromWebSite(token);
} while (result == -1);
return result;
}
It seems to me that you want to know how to stop the recursion. This is normally done with a condition where the result is clear and returned without calling the recursive function again. This way the endless calling of the recursive method is stopped and the recursion will come to an end. You dont use a goto for that like you simply never should use goto ;)
No, recursive calls are not equivalent to goto statements.
You don't even need to use recursion to solve your problem. If you place your call to GetNewToken in the loop, you can check the result and use continue to perform another iteration if you don't get the desired results. If you do get the desired result, you can call GetResultFromWebSite and return its result immediately.
I have the following recursive code and i am getting a stackoverflow exception. I can't figure out the root cause because once i get the exception,i dont get the full call stack in Visual studio.
The idea is that there are org teams that roll up into larger "Main" teams.
Does anyone see a flaw on this code below that could be the culprit?
private Unit GetUnit(Unit organisationalUnit)
{
if (organisationalUnit.IsMainUnit)
{
return organisationalUnit;
}
if (organisationalUnit.Parent == null)
return null;
return GetUnit(organisationalUnit.Parent);
}
You might have a unit which is its own parent, or barring that you might have a cycle of parents (e.g. A-B-C-A). That is, the problem might be with the data, not with the code per se.
Verify that the getters of IsMainUnit and Parent don't call GetUnit.
Does the root always have Parent == null?
Tried checking
if (organisationalUnit.Parent == organisationalUnit)
return null;
?
You could try this to debug it better. It won't affect your production code.
using System.Diagnostics;
private Unit GetUnit(Unit organisationalUnit, int depth)
{
debug.assert(depth < 10, "Reached an unexpected high recursion depth");
if (organisationalUnit.IsMainUnit)
{
return organisationalUnit;
}
if (organisationalUnit.Parent == null)
return null;
return GetUnit(organisationalUnit.Parent, depth + 1);
}
private Unit GetUnit(Unit organisationalUnit)
{
return GetUnit(organisationalUnit.Parent, 0);
}
On second thought...
It's mostlikely that you have a circular reference somewhere.
A.parent = B;
B.parent = C;
C.parent = A;
You could try to pass a set of previous visited nodes and check whether or not you've visited this node before.
The thing with recursion is that you have to be sure that it will end and an unchecked circular reference is a situation where it wouldn't end.
Is there any reason not to recode it as an iteration? That way, it'd be easier to set a hard limit on the depth of the organizational tree in order to catch bad (cyclic) data.
Recursion is fun, and tail optimizations can even make it efficient, but here it seems a like large hammer for a small problem.
I don't know much about visual studio.
But you should check for recurrence. e.g.
private Unit GetUnit(Unit organisationalUnit)
{
GetUnit(organisationalUnit, new vector());
}
private Unit GetUnit(Unit organisationalUnit,vector x)
{
if (organisationalUnit.IsMainUnit)
{
return organisationalUnit;
}
if (organisationalUnit.Parent == null)
return null;
x.add(this);
if(x.contains(organisationalUnit.Parent)) throw new Exception("recurrent parent");
return GetUnit(organisationalUnit.Parent,x);
}
One way to do that would be to reduce the stack size so it can crash earlier on.
You could do that by wasting frames upon the beginning of the program, i.e. to get a stack trace like: f_n,f_(n-1),...,f_1,waste,waste,...,waste, as in (in C pseudo-code)
int wasted = 1;
waste(int n,void (*f)())
{ if (n > 0) waste(n - 1,f) else f ();
wasted += 1; }
main () { waste(N,mainprime); }
where mainprime is your old main, and N is big enough to reach the f_1 you want.
The code looks OK, maybe you have some closed cycles in the Unit tree? Try to add trace lines with organisationalUnit.GetHashCode values, trace output is not limited and can help to detect stack overflow reason.
I guess you could avoid recursion by rewriting this along the lines of
while(organisationalUnit!=null && !organisationalUnit.IsMainUnit)
organisationalUnit=organisationalUnit.Parent;
return organisationalUnit;
I hope that helps.
EDIT: I just realized this would still fail if you have some sort of cyclic dependency.
You might have a cycle in your graph (see, it's not a tree).
You can use code like this to detect it:
private Unit GetUnit(Unit organisationalUnit) {
return GetUnit(organisationalUnit, new HashSet<Unit>());
}
private Unit GetUnit(Unit organisationalUnit, HashSet<Unit> visited) {
if (visited.Contains(organisationalUnit)) {
throw new Exception("Cycle detected!"); // or just return null if you prefer
}
visited.Add(organisationalUnit);
if (organisationalUnit.IsMainUnit) {
return organisationalUnit;
}
if (organisationalUnit.Parent == null)
return null;
return GetUnit(organisationalUnit.Parent, visited);
}
I was writing some try-catch blocks for various methods today, and thought to myself it would be good to have utility method which would automatically call the method again for a number of times specified in a parameter, at a certain time.
However, I thought to myself, the method/property etc which will cause an exception will be at the top of the stacktrace (do property calls get put on the stacktrace?) in a single threaded application (so an application with no code relating to threading). So I can simply get the method name at the top and dynamically call it again.
So I would have code like:
string s = StackTrace.GetFrame(0).GetMethodName; (I can't remember the exact syntax).
With this method, I can execute it using an activator or one of several other ways.
But in a multi-threaded application, I could have several methods firing at once and I wouldn't know which one finishes first/last. So I can't expect a method for which I write a try-catch block to be at the top of the stack.
How would I go about achieving this?
Please don't do this. It's a really, really, really, really, really bad idea.
Maybe not as bad as deleting files randomly, if the hard drive runs out of room - but just about as bad.
While I question the need for an auto retrying mechanism (does randomly retrying really help you out in so many situations that you need a utility method?) - using StackTrace and Reflection is, at best, a terribly complicated solution.
Not that I suggest that anyone actually use this code, but I'd probably go with a delegate based approach to this particular problem:
public static class Extensions {
public static void Try(this Action a, int maxTries) {
new (Func<bool>(() => { a(); return true; })).Try(maxTries);
}
public static TResult Try<TResult>(this Func<TResult> f, int maxTries) {
Exception lastException = null;
for (int i = 0; i < maxTries; i++) {
try {
return f();
} catch (Exception ex) {
lastException = ex;
}
}
throw lastException;
}
}
Usage is a bit unorthodox, but fairly clear I think:
// Set a property
new Action(() => myObject.Property = 5).Try(5);
// With a return value
var count = new Func<int>(() => myList.Count).Try(3);
You can't inline a lambda to a method, but you could have a somewhat fluent interface:
Utilities.Try(
() => MyObject.Property = 5
).Repeat(5);
And multi line methods:
Utilities.Try(() => {
MyObject.Property1 = 5;
MyObject.Property2 = 6;
MyObject.Property3 = 7;
}).Repeat(5);
Mark's code is probably better, but here's mine...
If you really want to do something like this, I'd use code something like this. Yes, you still have to manually call it, but your idea of indiscriminately retrying ALL excepting methods is a really, really bad idea.
public class TryAgain
{
public delegate void CodeToTryAgain ();
public static void Repeat<E>(int count, CodeToTryAgain code) where E : Exception
{
while (count-- > 0)
{
try
{
code();
return;
}
catch (E ex)
{
Console.WriteLine("Caught an {0} : {1}", typeof(E).Name, ex.Message);
// ignoring it!
}
}
}
}
And then you'd call your failing method, ThrowTwice, or whatever you want to do, like this:
TryAgain.Repeat<MyException>(5, delegate()
{
ThrowTwice();
});
In this example, the Repeat method will ignore all exceptions of type MyException, trying to call ThrowTwice up to 5 times...
You can add your own sleeping and time-outs, and whatever.