C# checkBox Logic .NET - c#

I am trying to write this Program that gives the user the checkBox and then the user chooses One or Two and the Program will return the answer accordingly. but the program is not accepting the && Operator. if the user checks two boxes the program is only returning the result of the first checkBox not the second. it is not even adding.
This is the Code:
private double Oillube()
{
//checking if the Oil is checked
if (oilChbox.Checked)
{
return OIL_CHANGE;
}
//checking if the lube is checked
if (lubeChbox.Checked)
{
return LUBE_JOB;
}
//if they are both checked
if(lubeChbox.Checked && oilChbox.Checked)
{
//Creating Variables sum to hold the value of the two
double sum;
sum = OIL_CHANGE + LUBE_JOB;
//returning sum
return sum;
}
else
{
//just returning to get ride off the red line under the Method
return 0;
}
}

Since the AND condition is more restrictive than the others, you should check it first. Like this:
private double Oillube()
{
//if they are both checked
if(lubeChbox.Checked && oilChbox.Checked)
{
//Creating Variables sum to hold the value of the two
double sum;
sum = OIL_CHANGE + LUBE_JOB;
//returning sum
return sum;
}
//checking if the Oil is checked
if (oilChbox.Checked)
{
return OIL_CHANGE;
}
//checking if the lube is checked
if (lubeChbox.Checked)
{
return LUBE_JOB;
}
//just returning to get ride off the red line under the Method
return 0;
}

The lubeChbox.Checked && oilChbox.Checked condition needs to go first, as it is the more specific of the two.
The way you have it now if either lubeChbox.Checked is true, or oilChbox.Checked is true it will return before reaching the lubeChbox.Checked && oilChbox.Checked condition, meaning there is no situation in which it could ever reach the condition unless both were false.
This is why it is typically a bad idea for people to use return in this manner unless they fully understand the flow of the code they want to achieve.
Here's the corrected code:
private double Oillube()
{
//if they are both checked
if(lubeChbox.Checked && oilChbox.Checked)
{
//Creating Variables sum to hold the value of the two
double sum;
sum = OIL_CHANGE + LUBE_JOB;
//returning sum
return sum;
}
//checking if the Oil is checked
if (oilChbox.Checked)
{
return OIL_CHANGE;
}
//checking if the lube is checked
if (lubeChbox.Checked)
{
return LUBE_JOB;
}
//just returning to get ride off the red line under the Method
return 0;
}
Alternatively you can use tertiary operators for this situation like so:
private double Oillube()
{
return (lubeChbox.Checked ? LUBE_JOB : 0) + (oilChbox.Checked ? OIL_CHANGE : 0);
}
A tertiary operator works the same as an if statement only they work inline.
So this:
(lubeChbox.Checked ? LUBE_JOB : 0)
is equivalent to this pseudo-code:
if(lubeChbox.Checked) { LUBE_JOB } else { 0 }
Dotnetfiddle example

It's because if the first checkbox is checked, then first if statement is true, so you are returning value, thus ending the method.
You should replace your if statements, last one should become first, as it is most restrictive.

Related

How do I fix a DivideByZeroException

I am using DevExpress XAF Framework.
I have a Class with a lot of Persistent Alias Attributes that does some math on the properties. Here is an example of my code:
[PersistentAlias("ShortTermDebt + LongTermDebt / EquityTotal")]
public decimal DebtEquity
{
get
{
return decimal.Parse(EvaluateAlias("DebtEquity").ToString());
}
}
I have tried setting the Property to = 1
return DebtEquity = 1;
But all this does is reset the property to 1 on saving.
I have tried setting the Default Value in SQL Server for each property to 1. But this does not work either.
Basically, I have a Detailview that has a bunch of calculations on it. And when I want to create a NEW Detail View, I get a DivideByZeroException because of course a NEW Detail View/Object is not going to have any values. Any ideas how I can get around this?
If you can get the value of EquityTotal then you can check it for zero first, otherwise you can catch the exception.
Example with check value first:
[PersistentAlias("ShortTermDebt + LongTermDebt / EquityTotal")]
public decimal DebtEquity
{
get
{
if (EquityTotal == 0) return 0; // return 0 or whatever number you want when EquityTotal is equal to zero
return decimal.Parse(EvaluateAlias("DebtEquity").ToString());
}
}
Example with catch exception:
[PersistentAlias("ShortTermDebt + LongTermDebt / EquityTotal")]
public decimal DebtEquity
{
get
{
try
{
return decimal.Parse(EvaluateAlias("DebtEquity").ToString());
}
catch (DivideByZeroException)
{
return 0; // return 0 or whatever number you want when EquityTotal is equal to zero
}
}
}
As an alternative using pure criteria language syntax, you can use:
[PersistentAlias("Iif(EquityTotal > 0,ShortTermDebt+LongTermDebt/EquityTotal, 0)")]
public decimal DebtEquity
{
get => Convert.ToDecimal(EvaluateAlias(nameof(DebtEquity)))
}

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;

Passing Structures between Managed and Unmanaged Code

I call c++/cli method from c# in this method:
bool SetProperty(Element element, Node referencePoint, List<Materializer> materializers, List<ulong> properties)
{
// Loop over STLs
for (int i = 0; i < materializers.Count; i++)
{
Materializer materializer = materializers[i];
PentalTreeNode pentalTreeRoot = pentalTreeDatasets[i].top;
if (materializer.IsPointInside(referencePoint.X, referencePoint.Y, referencePoint.Z, pentalTreeRoot))
{
element.PropertyId = properties[i];
return true;
};
}
return false;
}
C++/cli method is this:
bool IsPointInside(double x, double y, double z, PentalTreeNode ^root)
{
int intersectionCount = 0;
Math3d::M3d rayPoints[2], intersectionPoint;
rayPoints[0].set(x,y,z);
rayPoints[1].set(x,y,1.0e6);
if(_box->IsContainingPoint(x,y,z))
{
intersectionCount=CountIntersects(x,y,z,root);
return (intersectionCount%2!=0);
}
}
What is wrong, because c++/cli method doesn't return always the same result?
How to pin or marshal?
Method in c++/cli(Maybe this not ok?):
int CountIntersects(double x, double y, double z, PentalTreeNode ^root)
{
Math3d::M3d rayPoints[2], intersectionPoint;
rayPoints[0].set(x,y,z);
rayPoints[1].set(x,y,1.0e6);
if(!root)
return 0;
else
{
int special = CountIntersects(x,y,z,root->special);
if (x <= root->xMax && x >= root->xMin && y <= root->yMax && y >= root->yMin)
{
if( _stlMesh->IsRayIntersectsPoly(root->index, rayPoints, intersectionPoint))
{
return (1 + special);
}
else
return special;
}
else
{
if (y>root->yMax)
{
return (CountIntersects(x,y,z,root->top)+special);
}
else if(y<root->yMin)
{
return (CountIntersects(x,y,z,root->bottom)+special);
}
else if(x<root->xMin)
{
return (CountIntersects(x,y,z,root->left)+special);
}
else if(x>root->xMax)
{
return (CountIntersects(x,y,z,root->right)+special);
}
else
return special;
}
}
}
if( _stlMesh->IsRayIntersectsPoly(root->index, rayPoints, intersectionPoint))
There's one possible flaw in this particular statement, you've never initialized intersectionPoint. C++ lets you get away with this, it doesn't have anything similar to C#'s definite assignment rules. It isn't 100% clear whether that's the real problem, the variable might be passed by reference.
In the Debug build, such an uninitialized variable will have a predictable value. Something you can easily see in the debugger when you switch it to hexadecimal display mode. Fields in this struct or class will contain the value 0xcccccccc, a value that's apt to generate nonsensical results or crash your code with an access violation. In the Release build, the /RTC option isn't turned on and you'll get entirely random values in the variable.
Which corresponds very well with the description of your problem, so high odds that this is indeed the problem. Be sure to use the debugger to find problems like this, you can easily see the value of local variables with the Autos debugger window as you single-step through the code.
You are not calling a C++ method! You are calling a C++/CLI method. And therefore it is normal .NET code and it is always passed correctly. There is no need to pin or marshal anything in C# im this case!
If it returns not the expected values, you should try to find the problem in you C++/CLI project.

Recursion experimenting

I'm trying to experiment with recursion so as to grasp the concept. It is language agnostic, so the same concept applies to both C# and Java.
I've got a TreeView which has a number of nodes. I would like to iterate through every single node and count the ones which satisfy a certain condition. If at any time the condition is not satisfied, I would like the algorithm to finally return -1.
Each TreeViewItem will only be considered if it has a Tag named "Condition" (there are 3 types of TreeViewItems in all - I will only consider the "Condition" ones).
Once a TreeViewItem is found to be of the "Condition" type, I would like to check to see that it satisfies a certain condition. As I mentioned before, even if only one TreeViewItem does not satisfy the condition, I want the algorithm to return -1 in the end.
If the algorithm does not return -1, I want it to return the amount of valid conditions which it has found - i.e. an integer is to be incremented each time a condition is successfully passed, and the final count is returned at the end.
This is what I've tried so far:
private int CountConditions(TreeViewItem item)
{
int conditionCount = 0;
foreach (TreeViewItem child in item.Items)
{
int previousCount = CountConditions(child);
if (previousCount == -1)
{
return -1;
}
else
{
return conditionCount += previousCount;
}
}
if (item.Tag.Equals("Condition"))
{
if (/*Condition is not satisfied*/)
{
return -1;
}
else
{
return conditionCount++;
}
}
else
{
return conditionCount;
}
}
My current algorithm does infact return -1 if a condition is not satisfied, however if conditions are satisfied it just returns 0, rather than the amount of valid conditions.
you use
return conditionCount++;
which is bad practice. for good reason. what happens here is
a)return conditionCount (which you set to zero)
b)increment conditionCount
b never happens as its after the return statement, so you always pass 0 to your next recursion step.
you can use
return ++conditionCount;
or the much better
conditionCount++;
return conditionCount;
It is not a trivial recursion, since you have to handle both the error condition, and the normal condition. If you didn't have the error condition, and only needed to count the number of condition nodes, you could write:
private int CountConditions(TreeViewItem item)
{
int currentCondition = CalculateCondition(item)
int childCounts = 0;
foreach (TreeViewItem child in item.Items)
{
int childCount = CountConditions(child);
childCounts += childCount;
}
return currentCondition + conditionCounts
}
private int CalculateCondition(TreeViewItem item)
{
if (item.Tag.Equals("Condition"))
return 1;
else
return 0;
}
But to handle the error, you have to have two checks for the error condition, one for the current node, and one for the child nodes, and return immediately, if you encounter the condition:
int error = -1
private int CountConditions(TreeViewItem item)
{
int currentCondition = CalculateCondition(item)
if (currentCondition == error) // new
return error; // new
int childCounts = 0;
foreach (TreeViewItem child in item.Items)
{
int childCount = CountConditions(child);
if (childCount == error) // new
return error; // new
childCounts += childCount;
}
return currentCondition + conditionCounts
}
private int CalculateCondition(TreeViewItem item)
{
if (item.Tag.Equals("Condition"))
if (((item.Header as StackPanel).Children[2] as TextBox).Text.Equals("")) // new
return error; // new
else // new
return 1;
else
return 0;
}
You should return conditionCount; only at the end of the function. Only the return -1; have to be in the middle of the function.
return stops the whole function at once and returns a value. That's not what you want. You want to accumulate values and return the sum when you have finished.
I think you could simplify your code by using exceptions. What you do is you throw an exception when the condition fails which you can then catch in another function which starts of the recursion. This will automatically unwind the stack and abort the computation. The function which catches the exception can then return whatever you want it to.
Apart from this all you would have to do in the recursion is accumulate 1 for each passed condition.

C#... Not all code paths return a value

I am trying to create a Collection with properties and their respective accessors.
Here is my code:
class SongCollection : List<Song>
{
private string playedCount;
private int totalLength;
public string PlayedCount
{
get
{
foreach (Song s in this)
{
if (s.TimesPlayed > 0)
{
return s.ToString();
}
}
}
}
public int TotalLength
{
get
{
foreach (Song s in this)
{
int total = 0;
total += s.LengthInSeconds;
}
return total;
}
}
}
I'm receiving the error at the "get" point. It tells me that not all code paths return a value... What exactly does this mean, and what am I missing?
Firstly, the reason you're getting that message is that if this is empty, then the code within the foreach block (which is where the required return statement is) would never be executed.
However, your TotalLength() function would always return the length of the first Song, as you're declaring your variable, setting its value, then returning it within the foreach block. Instead, you'd need to do something like this:
int totalLength = 0;
foreach(Song s in this)
{
total += s.LengthInSeconds;
}
return totalLength;
Your PlayedCount function suffers from similar issues (if the collection is empty or contains no elements whose TimesPlayed property is greater than 0, then there would be no way for it to return a value), so judging by your comment you could write it this way:
public int PlayedCount()
{
int total = 0;
foreach(Song s in this)
{
if (s.TimesPlayed > 0)
{
total++;
}
}
return total;
}
It means just as it says, not all code paths return a value.
In this case, if your list is empty, then it cannot call return. In a foreach, there must be at least one item for the code to execute. Now, maybe you know that the list will always contain a value, but the compiler can't know that
What would your method return if this did not evaluate?
if (s.TimesPlayed > 0)
{
return s.ToString();
}
try using an else to return an empty string or something
The fact that 'this' could have no songs- in that case the loops will not execute at all and there is no implicit return value in C#.
Furthermore, your getters don't really make sense unless you only ever had one song in the collection. You need something more like this:
public int TotalLength()
{
get
{
int total = 0;
foreach (Song s in this)
{
total += s.LengthInSeconds;
}
return total;
}
}
Finally, without knowing how you keep track of TimesPlayed for each individual song, I wouldn't know how to implement that getter, but I am sure you can figure it out with this much.

Categories

Resources