Combining for and if loops together - c#

New to programming and reading a how to book. Question is about loops. I have the following code:
public bool DoThisJob(string job, int numShift) {
if (!string.IsNullOrEmpty(currentJob))
return false;
for (int i = 0; i < jobsICanDo.Length; i++) {
if (jobsICanDo[i] == job) {
currentJob = job;
this.shiftsToWork = numberOfShifts;
shiftsWorked = 0;
return true;
}
return false;
If the currentJob string is not empty then return false or return true? There is no else statement so how do we know what to do if it is true?.
Next run a for loop and again is the for loop ran because it returned false or true? Last run an if statement which is self explanatory.

There is no else because of the "return" statement. It immediately aborts execution of the function and returns to the calling function. You could write it with an else and it will function the same.

There is no else statement so how do we know what to do if it is true?.
in an if ... else (or classically called if .. then .. else) construct else if optional and in its absence it would fall through to the next statement outside the if block, in this case its the for statement
Your above function can be equivalently though to be similar to
public bool DoThisJob(string job, int numShift) {
if (!string.IsNullOrEmpty(currentJob))
return false;
else {
for (int i = 0; i < jobsICanDo.Length; i++) {
if (jobsICanDo[i] == job) {
currentJob = job;
this.shiftsToWork = numberOfShifts;
shiftsWorked = 0;
return true;
}
return false;
}

If the currentJob string is null then the if statement won't be run, and it will fall through to the for loop.
If the conditions in the for loop trigger it to return true then the method returns true and the last return is never reached.
If the for loop doesn't return true it will fall onto the last line and the method will return false.

A return statement stops the execution of the function at that point and returns control to the calling procedure.
public bool DoThisJob(string job, int numShift) {
if (!string.IsNullOrEmpty(currentJob))
return false; // If it is not empty then function call returns from this statement
// Else, flow control falls through and below code is executed
for (int i = 0; i < jobsICanDo.Length; i++) {
if (jobsICanDo[i] == job) {
currentJob = job;
this.shiftsToWork = numberOfShifts;
shiftsWorked = 0;
return true;
}
return false;
}
I hope, this clarifies the question.

Your function can be simplified as follows without a loop;
public bool DoThisJob(string job, int numShift) {
if (!string.IsNullOrEmpty(currentJob) || !jobsICanDo.Contains<string>(job))
{
//if currentJob NOT null/empty OR
//job is not in the jobsICanDo[] array
return false;
}
else
{
currentJob = job;
this.shiftsToWork = numberOfShifts;
shiftsWorked = 0;
return true;
}
}

Related

Means to count how many times a recursion was called or how to identify if all recursions were done and the code returned to the first call

I'm in need of means to check if how many times the recursive part of this function was activated to check when the first call was fulfilled, it's part of the designed true game over that needs the first call to be fulfilled without achieving all objectives.
IEnumerator CompositeRun(string name)
{
BotOperation operation;
compositeOps.TryGetValue (name, out operation);
CompositeOperation compOp = operation as CompositeOperation;
List<BotOperation> botOpList = compOp.opList;
if (botOpList != null)
{
for (int i = 0; i < botOpList.Count; i++)
{
BotOperation op = botOpList [i];
CompositeOperation comp = op as CompositeOperation;
if (comp != null)
{
// If this operation is a composite type, then we need to execute it first accordingly.
yield return StartCoroutine (CompositeRun(comp.name));
}
if (op != null && op.ValidateOperation(gameObject, levelDef))
{
op.RunOperation (gameObject, levelDef);
if (CheckGameOver ())
{
// If all objectives are fulfilled, then there's no need to continue running the processes, the stage is concluded.
StopAllCoroutines ();
}
}
yield return new WaitForSeconds (operationDelay);
}
}
yield return null;
}
I suggest starting with passing the recursion depth value
But are you 100% sure you cannot resolve this without recursion? Recursion seems like a heavy cannon to kill a fly here
IEnumerator CompositeRun(string label, uint recursionDepth = 0)
{
compositeOps.TryGetValue (label, out var operation);
var compOp = operation as CompositeOperation;
var botOpList = compOp.opList;
if (botOpList != null)
{
var delay = new WaitForSeconds (operationDelay);
for (int i = 0; i < botOpList.Count; i++)
{
var op = botOpList[i];
var comp = op as CompositeOperation;
if (comp != null)
{
// If this operation is a composite type, then we need to execute it first accordingly.
yield return StartCoroutine (CompositeRun(comp.name,recursionDepth+1));
Debug.Log($"we need to go deeper # depth:{recursionDepth+1}");
}
if ( op?.ValidateOperation(gameObject, levelDef))
{
op.RunOperation (gameObject, levelDef);
if (CheckGameOver ())
{
// If all objectives are fulfilled, then there's no need to continue running the processes, the stage is concluded.
StopAllCoroutines ();
}
}
yield return delay;
}
}
yield return null;
}

Get n from findelement in findelements iteration

I'm searching an element inside elements list. And if an element found I return the n of iteration.
I'm wondering is there is another faster way to do that? Currently I can do that purpose this way. But it takes time to process.
var iBtnFix = 0;
var elProfiles = driver.FindElements(By.ClassName("xxx")); // list
for (var i = 0; i < elProfiles.Count; i++)
{
try
{
elProfiles[i].FindElement(By.XPath(".//button[contains(#class,'yyy')]"));
iBtnFix = i;
break;
}
catch (Exception ex)
{
}
}
Better to use if-else condition with return statement instead of try-catch block. You can create method isElementVisible() which return boolean based on visibility of element and use its response in your if condition.
For example :
if(isElementVisible("your locator")
{
return index;
}
Method for example :
public boolean isElementVisible(By by){
boolean isElement = false;
try{
isElement = driver.findElement(by).isDisplay();
}catch(NoSuchElementFoundException e){
isElement = false;
}
return isElement;
}
This is java code. You can write according in C#.

Run IEnumerator functions once counter hits certain number

All! I'm trying to run a process once my counter hits a certain number.
I currently have this part of code on my Update function:
if (counter == 17)
{
// must call process here
}
This is the process I want to run
private void CallProcess()
{
StartCoroutine(StartProcess());
}
This is the whole code for the IEnumerator
private IEnumerator StartProcess()
{
yield return StartCoroutine (Process1()); //once done, a bool here is set to true
if (proccess1_done)
{
yield return StartCoroutine (Process2());
if (process2_done)
{
process1_done = false;
process2_done = false;
}
}
}
I encounter problems when I just call CallProcess() inside my update bc it gets called over and over again. Any advice on how I should modify my code would be much appreciated.
Don't call the StartCoroutine in update. Instead, wrap the boolean in a property so when it is changed or set, you can also call the StartCoroutine.
Let's say counter is the one that sets it:
private IEnumerator coroutine = null;
private int counter = 0;
public int Counter
{
get{ return this.counter; }
set
{
this.counter = value;
if(this.counter == conditionValue)
{
if(this.coroutine != null){ return; } // already running
this.coroutine = StartProcess();
StartCoroutine(this.coroutine); }
}
}
and for your coroutine:
private IEnumerator StartProcess()
{
yield return StartCoroutine (Process1());
yield return StartCoroutine (Process2());
}
you don't really need to check whether Process 1 is done since your coroutine is already waiting for it to be done before continuing.
if you need to check for something inside process 1 for process 2 to run, here is a solution:
private IEnumerator StartProcess()
{
bool condition = false;
yield return StartCoroutine (Process1(ref condition));
if(condition == false){ yield break; }
yield return StartCoroutine (Process2());
this.coroutine = null;
}
private IEnumerator Process1(ref bool condition)
{
// some code
yield return null;
// more code
condition = true; // or false
}

How do you return true for a boolean return type if you have a for block to execute

So i was reading this question return True stop the loop in Python? but its in python and im in c#
anyways i have a method that looks like this
public bool HasRequirements(string upgradeName){
for (int i = 0; i < upgradeRequirements [upgradeName].Length; i++) {
if (upgradesPurchased [upgradeRequirements [upgradeName] [i]]) {
return true;
} else {
return false;
}
}
return false;
}
While coding this I figured that returning true would stop the execution of the for block so then I got to thinking how would you return true for a boolean return type when you have a for block to execute?
Based on your comments, another extended function which does only return true if all iterations are true:
public bool HasRequirements(string upgradeName){
for (int i = 0; i < upgradeRequirements [upgradeName].Length; i++) {
if (upgradesPurchased [upgradeRequirements [upgradeName] [i]]) {
// we skip return true
continue;
} else {
// false condition, immed return false
return false;
}
}
// we did not met false - so we can return true
return true;
}
If you want to get 'multiple results' - another possibility is to use the yield statement. You can find an so post describing it in details here: What is the yield keyword used for in C#?
Using yield which does continue returning the values based on the following enumerations. Afterwards the return value could be checked if all are true:
public IEnumerable<bool> HasRequirements(string upgradeName)
{
bool returnValue = false;
for (int i = 0; i < upgradeRequirements[upgradeName].Length; i++)
{
if (upgradesPurchased[upgradeRequirements[upgradeName][i]])
{
yield return true;
}
else
{
yield return false;
}
}
yield return returnValue;
}
"if one component has not been bought then it should return false otherwise if all components are bought then it should return true"
Maybe you need to think revert from where you have been heading:
public bool HasRequirements(string upgradeName)
{
for (int i = 0; i < upgradeRequirements [upgradeName].Length; i++)
{
if (upgradesPurchased [upgradeRequirements [upgradeName] [i]])
{
continue;
} else {
return false; // if one component has not been bought
}
}
return true; // all components were bought
}
Now if the current purchase being checked is done, then continue to next, basically ignore it and move on. But if one is not done, it is enough to consider the current state faulty so return false and discard anymore checks since it will be false in the end whatsoever.

skip a for-loop but from function which is called inside that loop in c#

hey guys m running into a problem, i have a forloop n in that i call a function, and in that function i have a if condition, i want to skip 1 loop if condition gets true, for this problm i was thinkin' to use goto statement but as i read in many forums that goto statement is an evil... can it be solved without using goto statement, ne ideas i dn't want to use 'goto'
for(int i=0;i<gridview.rows.count-1;i++)
{
//some operation;
aFunction(param1,param2);
}
public void aFunction(param1,param2)
{
//some operation;
if (!Regex.IsMatch(RechargeText, "successfully"))
{
RechargeStatus = "Failed";
Program.sp.SoundLocation =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) +
"/aimlife_error.wav";
Program.sp.Play();
}
else if (Regex.IsMatch(RechargeText, "Processing") || Regex.IsMatch(RechargeText, "Not"))
{
// here i need to skip the Loop
}
else
{
Program.sp.SoundLocation =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) +
"/aimlife_success.wav";
Program.sp.Play();
}
Program.StatusMessage = "Recharge Successful";
TextFill();
}
Actually there are some error list that are accepted errors, so i dn't need to update that in db, So my TextFill(); function shud not run for accepted errors
Snippet Edited
Simple, have the method return a bool. Then you can do:
for(int i=0;i<gridview.rows.count-1;i++)
{
//some operation;
if (aFunction(param1,param2)) break;
}
goto won't help you anyway. Basically you can't continue from a different method at all. The only simple way you can keep roughly your current flow is something like this:
bool shouldSkipNext = false;
for (int i = 0; i < gridview.Rows.Count - 1; i++)
{
if (shouldSkipNext)
{
shouldSkipNext = false;
continue;
}
// some operation
shouldSkipNext = aFunction(param1, param2);
}
public bool aFunction(param1,param2)
{
if (abc)
{
return true;
}
// Other stuff
return false;
}
Note that this will skip the entirety of the next iteration of the loop - which isn't the same as just continue. If you have more code after the call to aFunction and you want to skip that (which is the equivalent of continue) then it's simpler:
for (int i = 0; i < gridview.Rows.Count - 1; i++)
{
// some operation
if (aFunction(param1, param2))
{
continue;
}
// Other stuff which will sometimes be skipped
}
All you want to do is skip executing the TextFill() function when the condition if (Regex.IsMatch(RechargeText, "Processing") || Regex.IsMatch(RechargeText, "Not")) is true, thats all right?
You can simply return at that if condition, which will work out as you want:
else if (Regex.IsMatch(RechargeText, "Processing") || Regex.IsMatch(RechargeText, "Not"))
{
return;
} .... // rest of the code as it is
now when the above condition works out as true it will return to the for loop and go with the next iteration and so on...
Cheers
for(int i=0;i<gridview.rows.count-1;i++)
{
//some operation;
if (!aFunction(param1,param2)) continue;
}
public bool aFunction(param1,param2)
{
//some operation;
if (!Regex.IsMatch(RechargeText, "successfully"))
{
RechargeStatus = "Failed";
Program.sp.SoundLocation =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) +
"/aimlife_error.wav";
Program.sp.Play();
}
else if (Regex.IsMatch(RechargeText, "Processing") || Regex.IsMatch(RechargeText, "Not"))
{
Program.StatusMessage = "Recharge Successful";
TextFill();
return false;
// here i need to skip the Loop
}
else
{
Program.sp.SoundLocation =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) +
"/aimlife_success.wav";
Program.sp.Play();
}
Program.StatusMessage = "Recharge Successful";
TextFill();
return true;
}
If your code as posted is exactly how it is, then you could simply return, as the loop has no other operations.
No, it can not be solved with a goto... thankfully.
There is nothing that you can do inside the method that will change the control flow in the loop, you have to return something from the method and use that in the code of the loop:
for(int i = 0; i < gridview.rows.count - 1; i++) {
//some operation;
if (aFunction(param1,param2)) {
// do something more here
}
}
public bool aFunction(param1,param2) {
//some operation;
if(abc) {
//skip the current for-loop i.e i want to do "continue" here;
return false;
} else {
//normal
return true;
}
}
public static void main(String[] args) {
int param1 = 0, param2 = 0;
getResult(param1, param2);
}
public static void getResult(Object param1, Object param2) {
for (int i = 0; i < gridview.rows.count - 1; i++) {
if (!Regex.IsMatch(RechargeText, "successfully")) {
RechargeStatus = "Failed";
Program.sp.SoundLocation = System.IO.Path
.GetDirectoryName(System.Reflection.Assembly
.GetExecutingAssembly().Location)
+ "/aimlife_error.wav";
Program.sp.Play();
} else if (Regex.IsMatch(RechargeText, "Processing")
|| Regex.IsMatch(RechargeText, "Not")) {
// just skip here then
continue;
} else {
Program.sp.SoundLocation = System.IO.Path
.GetDirectoryName(System.Reflection.Assembly
.GetExecutingAssembly().Location)
+ "/aimlife_success.wav";
Program.sp.Play();
}
Program.StatusMessage = "Recharge Successful";
TextFill();
}
}
You should extract
Program.sp.SoundLocation = System.IO.Path
.GetDirectoryName(System.Reflection.Assembly
.GetExecutingAssembly().Location)
+ "/aimlife_success.wav";
Program.sp.Play();
and
RechargeStatus = "Failed";
Program.sp.SoundLocation = System.IO.Path
.GetDirectoryName(System.Reflection.Assembly
.GetExecutingAssembly().Location)
+ "/aimlife_error.wav";
Program.sp.Play();
into its own methods to make this code clearer, looks like a mess.

Categories

Resources