How can this recursive function return true? - c#

This is my recursive function :
public bool controllaSelezioneSottopagina(KPage k_oPaginaAttuale, KPage k_oPaginaSuperiore)
{
foreach (KPage k_oSottoPagina in k_oPaginaSuperiore.SottoPagine)
{
if (k_oSottoPagina.ID == k_oPaginaAttuale.ID)
{
return true;
}
else
{
if (k_oSottoPagina.SottoPagine.Count != 0)
{
controllaSelezioneSottopagina(k_oPaginaAttuale, k_oSottoPagina);
}
}
}
return false;
}
I aspect, from where I call it, to get ALWAYS false (the return false at the end of the function, will be the last result that will be returned, EVER).
In fact, sometimes it returns true.
How it is possible? Tried debugging... but I can't find out the mistake...

You call the function once, then it loops, and either returns true or calls itself recussively. It will only return false if it loops through all elements and the condition (k_oSottoPagina.ID == k_oPaginaAttuale.ID) is never met.
Now assume that this condition is actually met in the first level (there was no recursion made yet or all recursive call return).
You call the function once, it loops and for example on the first test this condition is true. Then you will see a return value 'true'

I think this could happen only in first iteration. I mean that only first comparison may result in returning true. Recursive call would never happen then.

Are you saying this code block will never be true in the first call to the function (the first time through the loop)?
k_oSottoPagina.ID == k_oPaginaAttuale.ID
Since you don't return the result of the recursive call, your function either blows the stack, returns true through the first loop at some point, or finishes the loop and returns false.

another alternative to not printing incorrect false in the cases where it does go in the loop is
public bool controllaSelezioneSottopagina(KPage k_oPaginaAttuale, KPage k_oPaginaSuperiore)
{
foreach (KPage k_oSottoPagina in k_oPaginaSuperiore.SottoPagine)
{
if (k_oSottoPagina.ID == k_oPaginaAttuale.ID)
{
return true;
}
else
{
if (k_oSottoPagina.SottoPagine.Count != 0)
{
if(controllaSelezioneSottopagina(k_oPaginaAttuale, k_oSottoPagina))
{
return true;
}
}
}
}
return false;
}

Related

Does the method inside the IF condition always get executed? C#

if (condition)
{
// block of code to be executed if the condition is True
}
So if I have a method which returns boolean and the method is used as the condition for IF, does that method get executed no matter what?
Below is the code I'm working on:
public virtual void WorkTheNextShift(float HoneyConsumed)
{
if (HoneyVault.ConsumeHoney(HoneyConsumed))
{
DoJob();
}
else Console.WriteLine("Not enough honey left!");
}
This is the ConsumeHoney method in the static HoneyVault class:
public static bool ConsumeHoney(float amount)
{
if (amount < honey)
{
honey -= amount;
return true;
}
else return false;
}
Thank you for your help! :)
Additional question:
Is there any official documentation where it says that the condition inside IF will always be executed? I can't seem to find it under Microsoft's .NET documentation, or anywhere else.
In your case, yes: the method will always get executed.
Things can get a little more complex if you have multiple conditions. In this case something called short-circuit evaluation may come into play and the method may not be executed at all if the boolean condition can be satisfied regardless of it's result.
The following examples will help clarify it:
bool A = true;
bool B = false;
bool Test() {
Console.WriteLine("Test was called!");
return false;
}
if (Test()) {
// will call Test
}
if (B || Test()) {
// will call Test since B is false the compiler has to check Test()
}
if (A || Test()) {
// Test won't be called because A is true and the result
// of Test() is not needed. The condition is always true.
}
if (B && Test()) {
// Test won't be called because B is false and the result
// of Test() is not needed. The condition is always false.
}
if (A && Test()) {
// Will call Test since A is true. The compiler needs to check the
// result of Test to properly check the AND condition.
}
In the official documentation the && operator is described as: The conditional logical AND operator &&, also known as the "short-circuiting" logical AND operator.
While the || operator is described as: The conditional logical OR operator ||, also known as the "short-circuiting" logical OR operator
Here is a link to the docs: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/boolean-logical-operators

Unreachable code detected in the for loop

I'm trying to find out if a number is prime or not. But I've got an error of "unreachable code detected", which I think is effecting the error of "not all code paths return a value". The error seems to occur in the for loop at i++. Can anyone help me please?
static void Main(string[] args)
{
Console.WriteLine(isPrime(10));
}
public static bool isPrime(int n)
{
for (int i = 2; i < n; i++)
{
if (n % i == 0)
{
return false;
}
return true;
}
}
"Unreachable code detected" means that some code can never be executed. Consider:
int something()
{
if (true)
return 1;
else
return 2; //Obviously we can never get here
}
"Not all code paths return a value" means that you've defined a method with a return value (like "bool" in your example) and there is some way for the method to execute without returning a value.
Consider:
int something(bool someBool)
{
if (someBool)
return 1;
//if someBool == false, then we're not returning anything. Error!
}
Your code has two problems:
You have return true inside the for loop (outside of any conditional). Because return immediately exits the function (returning control to the caller) the i++ statement of the for loop will never get executed (hence your bug). You likely intended for that to be outside the for loop.
Another problem with that being in the loop is that the loop is not guaranteed to execute. If the n passed was 2 or less, you would skip the loop entirely, and there is no return statement in that case. This isn't allowed (since you always need to return a value from a non-void function) so you get a compiler error.
Below is an example of how to get this return working with a for loop and embedded If condition.
private bool WinOneLevelOne()
{
//For loop to check all the items in the winOne array.
for (int i = 0; i < winOne.Length; i++)
{
//If statement to verify that all the gameobjects in the array are yellow.
if (winOne[i].gameObject.GetComponent<MeshRenderer>().material.color != Color.yellow)
{
//Keeps the boolean at false if all the gameobjects are not yellow.
return false;
}
}
return true;

C# - Foreach loop with if statement

How can I go about doing this so if the "if" statement is true, to skip the code below the foreach loop and to go on with the rest of the program
void()
{
foreach()
{
if()
{
}
}
//code I want to skip if "if" statement is true
}
There's no way to directly do what you want (without "goto" labels -- perish the thought!), but you can use the "break" keyword, and set a variable you can refer to later.
void()
{
var testWasTrue = false;
foreach()
{
if()
{
testWasTrue = true;
break; // break out of the "foreach"
}
}
if( !testWasTrue ) {
//code I want to skip if "if" statement is true
}
}
I know this was already answered, but I figured I'd throw in my 2 cents since nobody considered abstracting the check to a separate method:
void()
{
if (ShouldDoStuff(myCollection))
DoStuff(myCollection);
else
DoOtherStuff(myCollection);
}
private bool ShouldDoStuff(collection)
{
foreach()
{
if ()
return true;
}
return false;
}
This provides a much cleaner code at the higher level for dealing with your algorithms and removes all the clutter discussed about. It cleanly separates the tasks in void() of checking and performing the actions and readers instantly know exactly what the program flow is without having to discern what they're doing with a boolean or break logic lurking about. No single method has more than 1 responsibility or task.
Yeah, it's possible the poster wants to do other work in their foreach, but that's an entirely different discussion and not what was described in their question. If you simply want to check if the given collection (or object) satisfies a certain condition, that check can be moved to a separate method. Even leaves the door open for automated unit tests for all three components.
Even if DoStuff and DoOtherStuff are not abstracted to their own methods, it provides nicer readability and logical flow.
void()
{
bool process = true;
foreach()
{
if()
{
process = false;
break;
}
}
if (process)
{
//code I want to skip if "if" statement is true
}
}
As was mentioned in my comment you may do this through extra bool variable.
void()
{
bool positiveResult; // by default it gets false value
foreach()
{
if()
{
positiveResult = true;
// you may use "break" to skip the loop
break;
}
}
if( !positiveResult )
{
//code I want to skip if "if" statement is true
}
}
The 'break' keyword will break out of the loop.
foreach (someClass a in someArray)
{
if(a.someProperty) // bool property
{
//Stuff to do if that condition is true
doSomethingElse();
//Calling the break keyword will stop the loop and jump immediately outside of it
break;
}
//Other code to run for each iteration of the loop
}
//Here is where execution will pick up either after break is called or after the loop finishes
Only way I know how is a bool flag.
void()
{
bool x = false;
foreach()
{
if()
{
x = true;
break;
}
}
if(!x)
{
//Code to skip if "if" statement is true.
}
}
Not super elegant, but easy.
Edit: beat by 12 secs :)
void()
{
bool skip = false;
foreach()
{
if()
{
skip = true;
}
}
if(!skip)
{
//code I want to skip if "if" statement is true
}
}
If the collection you are iterating through contains The IEnumerable Interface, You could use Any() with a Lambda!
int[] myArray = { 1, 2, 3 };
if( myArray.Any((a) => a == 1) )
{
return;
}
It is read: if my array contains any value a where a is equal to 1, then return out of this function.
Plus if you want to make it harder to read, you can omit the curly braces/brackets.
if( myArray.Any((a) => a == 1) )
return;

Return value from For loop

I have a listView in my app. I loop through the items to check which one is currently selected and then return a value. As all paths have to return a value I have to return a value outside the loop which overwrites the for loop return, how do I keep this without overwriting it after the loop?
public string GetItemValue()
{
for (int i = 0; i < listView1.Items.Count; i++)
{
if (listView1.Items[i].Checked == true)
{
return listView1.Items[i].Text; // I want to keep this value
}
}
// Without overwriting it with this but the compiler
// requires me to return a value here
return "Error";
}
Any help is most appreciated. Thanks.
P.S I have tried using break after the if but no luck.
On edit: bringing down my comment from above.
You don't need to worry about this. As soon as it hits the first return inside the loop, it will return immediately with that value. No code outside the loop is ever hit in that case.
Incidentally, this code would be cleaner:
public string GetItemValue()
{
foreach (var item in listView1.Items)
{
if (item.Checked) return item.Text;
}
throw new InvalidOperationException("No checked items found");
}
Exceptions are a more idiomatic way of handling errors, and the foreach loop is preferred to a for loop when you're just iterating over collections.
Also using LINQ, you can get even more concise:
public string GetItemValue()
{
return listView1.Items.Cast<ListViewItem>().Single(i => i.Checked).Text;
}
Well, your return outside of the loop, return "Error"; shouldn't get called based on your logic. Since return causes your method to immediately exit, the "Error" return will never happen, that is unless the code never steps into the if inside the loop.
All things considered, this may be an exceptional case in your code. Thus, throwing an exception may be the appropriate thing to do:
public string GetItemValue()
{
for (int i = 0; i < listView1.Items.Count; i++)
{
if (listView1.Items[i].Checked == true)
{
return listView1.Items[i].Text; // I want to keep this value
}
}
throw new InvalidOperationException("Did not find value expected.");
}
Exceptions are usually thrown to indicate that a bug exists in code. A "Hey, that should really not be happening." The application stops, and hopefully the user gets an opportunity to contact support to help you reproduce it.
Based on your comment:
When I run it, it just returns the error text...
That means your check in your if statement is not succeeding.
if (listView1.Items[i].Checked == true)
Which means that none of your items in your ListView are checked.
That's the kind of situations where you are probably better of throwing an exception in order to signal the exceptional situation:
public string GetItemValue()
{
for (int i = 0; i < listView1.Items.Count; i++)
{
if (listView1.Items[i].Checked == true)
{
// Here you are leaving the GetItemValue method
// and the loop stops
return listView1.Items[i].Text;
}
}
// if we get that far it means that none of the items of
// the select list was actually checked => we are better of
// reporting this to the caller of the method
throw new Exception("Please select a value");
}
The return in your for loop isn't overwritten -- the method will return the value in the loop if your conditions are met. Execution of the method ends immediately upon reaching a return statement.
If your method is returning "Error", then I'd recommend looking at your code in a debugger, because it's reaching the end of the loop and returning the value "Error".
If you're returning a value in the loop, it should not reach the return that's outside of the loop. I would check to make sure that the loop is finding the selected item.
The other option is to create a local variable to hold the return value:
string returnValue = "Error";
for (int i = 0; i < listView1.Items.Count; i++)
{
if (listView1.Items[i].Checked == true)
{
returnValue = listView1.Items[i].Text;
break;
}
}
return returnValue;
Lastly, you might also consider returning an exception when no selections are found, and handling the exception from the calling method.
The return "Error" bit will not overwrite your loop return value. When a return is hit, the function exits, so when a value that is selected is found, the function will spit out your data and stop.
The compiler requires that all paths of the function return a value. The compiler cannot know before hand whether your inner loop if condition will be met. You can cache the value at a variable and return this in the end of the function e.g. :
public string GetItemValue()
{
string temp = null;
for (int i = 0; i < listView1.Items.Count; i++)
{
if (listView1.Items[i].Checked == true)
{
temp = listView1.Items[i].Text; // I want to keep this value
break;
}
}
return temp; // Without overwriting it with this but the compiler requires me to return a value here
}
Actually, there is no need for a loop here:
return (listView1.SelectedItems.Count > 0)
? listView1.SelectedItems[0].Text
: "Error";
But, as it was said, the original question is misleading since return does not override values. You might be thinking about assignment, instead of return. In this case a working code can look like this:
string ret = "Error";
foreach(var item in listView1.Items)
{
if(item.Checked) { ret = item.Text; break; }
}
return ret;

When does the while loop check for its condition

Hi I have something like:
Version 1:
bool noErrors = true;
while(noErrors)
{
noErrors = ValidateControl(txtName);
// other code
}
Version 2:
bool noErrors = true;
while(noErrors)
{
if(!ValidateControl(txtName)) break;
// other code
}
I use this code to validate a form and if the validation returns false, I want to break before executing "other code". Since I do not know when the loop checks for its condition, I do not know which makes more sense. Should I use the first or the second version, or maybe a third one?
Thank you for your time
Version 2 will break before running the //other code. Version 1 will not check until the start of the next iteration.
bool noErrors = true;
while(noErrors)
{
noErrors = ValidateControl(txtName);
// other code
}
Checks before each iteration.
bool noErrors = true;
do
{
noErrors = ValidateControl(txtName);
// other code
} while(noErrors);
Checks after each iteration.
Neither check during an iteration. As stated by the other answerers, the following code simplifies the example but makes me ask the question, is the validity of txtName likely to change during the execution of the loop? Would some other limiting condition be more useful?
while (ValidateControl(txtName))
{
// other code
}
If the validity of txtName will not change, consider,
if (ValidateControl(txtName))
{
while(/*Some other condition*/)
{
// other code
}
}
The condition is only ever checked at the start of any possible iteration. So in version 1 the "other code" would be executed even if noErrors has been set to false in the first line of the body... whereas in version 2 it wouldn't... but noErrors looks like it's somewhat useless in version 2.
Could you change it to:
while (ValidateControl(txtName))
{
// other code
}
?
A while loop evaluates its condition before the first iteration, and inbetween each subsequent iteration. The condition is never evaluated inside the loop body.
It checks it before running again (first time, after first run and so on). You have to break or whole chunk of code will run.
The while loop checks the condition before it iterates over the block of code that it precedes. You can also make it check the condition at the end by using a do-while construct. Your version #2 will produce the result you desire.
The while loop checks the condition before executing the entire code block. If you want to break execution before the other code is executed, use Version 2.
The loop condition is only evaluated at the start of each loop, so in your first version, the "other code" will still be executed, even if ValidateControl returns false.
Your second version works better, and will not run the "other code" if ValidateControl returns false, however it also does not set noErrors to false if the validation fails. If that's not important, and noErrors is only the loop condition, then you might as well change your while loop to while(true), if it is used later in the code, then you'll need to change version 2 slightly:
bool noErrors = true;
while(noErrors)
{
if(!ValidateControl(txtName))
{
noErrors = false;
break;
}
// other code
}
If this is in a validation routine, I wouldn't even BOTHER with a WHILE() construct... In the past, I would typically test each specific validation routine that did just that... no looping involved such as
Function bool IsAllDataValid()
{
if ( ! (ValidateControl(txtName) )
return false;
if ( ! (ValidateControl(OtherField ))
return false;
etc...
return true;
}
Then you don't have to worry about where the mix is of include or bypass certain blocks of code... You could just have...
if IsAllDataValid()
{
Do Your Other Code
}

Categories

Resources