If Statement with Multiple Conditions vs Individual If Statements [duplicate] - c#

This question already has answers here:
"If" statement - Order of validation of objects?
(6 answers)
Closed 2 years ago.
I would like to check each condition and return if true.
Is it better to have:
1. Multiple conditions in a single if statement?
if (string.IsNullOrEmpty(myStr) ||
myBool == true ||
myList.Count == 0)
{
return;
}
2. Or multiple if statements, each checking a different condition.
if (string.IsNullOrEmpty(myStr))
{
return;
}
if (myBool == true)
{
return;
}
if (myList.Count == 0)
{
return;
}
If myStr is Empty.
My thought is that the first way checks all 3 conditions before it reaches the return (or does it)?
And the second way only has to check the 1st condition string.IsNullOrEmpty, reaches the return, and doesn't have to process the other 2 condition checks below it.
Or does the compiler optimize the code to work most efficient no matter how the source is written?

They are equivalent. The || operator short-circuits, so as soon as it reaches a condition that is true, it stops checking other conditions and returns true.
The | operator does not short-circuit, so it would evaluate every operand before returning a value.
Same goes for && and & but with false. As soon as a false condition is reached, the && operator returns false.
So your two methods are functionally identical. Use whichever one you think is the cleanest, easiest to infer intent, etc.
Or does the compiler optimize the code to work most efficient no matter how the source is written?
Well, the optimizer can make changes to code for efficiency, but it cannot change the functional behavior, meaning it won't change the order of the operations. Imagine you had something like:
if ((x == 0) || (y/x > 1))
this is a common way to prevent divide-by-zero errors. If the compiler could rearrange the operands, then it could introduce divide-by-zero errors.

It's a matter of preference really, as both will result in the same overall performance. Both are equivalent to each other. By default, C# uses short-circuit evaluation, meaning the if statement will stop as soon as it finds an expression that evaluates to true. Most of the time, I've seen it written as a single if statement, but separate checks can be easier for debugging if you want to put a breakpoint on one of the specific conditions.
Also of note, although if (myBool == true) will work, you don't have to explicitly equate it to true. The if statement just has to evaluate to true, so you can write it as if (myBool). Again it's personal preference, but it's shorter and can make it easier to read.
Lastly, you might consider using string.IsNullOrWhiteSpace, which is just like string.IsNullOrEmpty but also checks if the string only contains spaces, tabs, etc., with no content.

Related

If statement not checking multiple values

I am trying to test and see if 4 user inputted answers are correct(I have tested without using if statements and all variables are correct), however it seems to only be checking 1 out of the 4 conditions in the if statement. I tried using both the single & and double && operator, and neither made a difference?
if(isOneCorrect.ToUpper() == checkBox1.Checked.ToString().ToUpper() &&
isTwoCorrect.ToUpper() == checkBox2.Checked.ToString().ToUpper() &&
isThreeCorrect.ToUpper() == checkBox3.Checked.ToString().ToUpper() &&
isFourCorrect.ToUpper() == checkBox4.Checked.ToString().ToUpper())
{
MessageBox.Show("you won!");
}
What can I do to make the if statement make sure EVERY condition of the 4 is correct?
The boolean operators/expressions in C# shortcut - this means if you have several sequential boolean operators (like you have) then expression evaluation will stop when the overall result can no longer be changed.
So, to explain that a little more: you have four && operators. For the if statement to valuate to true all of those ANDed expressions need to evaluate to true. If the first one fails there is no point evaluating the rest, the final result will not change.
When comparing strings you should use the string.Equals() extension method.
However you did state in the comments that isOneCorrect is boolean; if checkBox1.Checked is also boolean then you do not need to convert anything to string, just compare the two booleans. If checkBox1.Checked is a nullable bool (bool?) then use the HasValue and Value properties to access it as a bool.

Does the order of appearance matter in a single IF statement with multiple conditions

I've got a Collection with up to 19,000 entries in it that I'm iterating over in a foreach statement. At the beginning of the foreach, I check if a string contains 1 of 2 words and a boolean value, then I either continue or perform some more operations.
foreach (SvnStatusEventArgs e in results) //results being my Collection
{
if ((e.Path.Contains("bin") ||
e.Path.Contains("obj")) && !includeBinObjFolders)
continue;
//Do a bunch of things
}
I wasn't sure if the computer would check the string for either "bin" or "obj", and then check the boolean and maybe it'd realize it didn't matter that the strings contained one of those two 'key words'.
Basically I guess what I'm saying is would the following take a different amount of time to run?
foreach (SvnStatusEventArgs e in results) //results being my Collection
{
if (!includeBinObjFolders &&
(e.Path.Contains("bin") ||
e.Path.Contains("obj")
)
)
continue;
//Do a bunch of things
}
For some reason, I hear a voice in the back of my head telling me that it evaluates the right-most expression first, and works its way left. If so, the first should be more efficient right? I don't have an easy way of testing a collection larger than ~200 files so simply using a timer yields results that are so close I can't confirm if one way is better.
Frankly I think it's highly unlikely end users will encounter more than 500 pieces of data in this collection at most, but theoretically it could happen due to user error.
Edit thanks everyone. I tried searching around before posting here but I forgot the term "short circuiting" in regards to logic so I was having a tough time finding an answer relevant to my wordy title here.
Edit 2 Actually I just went and created a small console application that had a 2 for loops iterating 20,000 times each. One tested the Contains first, the other tested the Bool first. Repeating these two loops 10 times over, it looks like the boolean first takes on average half of a millisecond per 20K iterations. The Contains being evaluated first takes roughly 3 milliseconds per 20K iterations. A small difference indeed!
The given boolean expressions will be evaluated from left to right, not right to left. The order is indeed defined; it is not arbitrary, nor can it be optimized. It will always be left to right.
This was specifically called out in the specs so that the side effects of each expression are always executed in a defined order.
You can, if you want, move the boolean variable to the front as an optimization. It may not be a huge optimization, so don't fret too much over it, but it is an optimization. (Unless of course you know that it will always, or almost always, resolve to true while another expression would resolve to false.)
The last expression would probably save you a little more on the runtime as you are only computing a boolean value first. If that's false, the rightmost expression won't even get evaluated, since false AND anything will be false.
Logical operators are processed left to right and && and || are shortcircuit operators; meaning
x || y // will evaluate x and if it's false, then it will evaluate y
x && y // will evaluate x and if it's true, then it will evaluate y
http://msdn.microsoft.com/en-us/library/aa691310(v=vs.71).aspx
your second approach would be faster
In this example, you are short-circuiting your evaluation using &&:
foreach (SvnStatusEventArgs e in results) //results being my Collection
{
if (!includeBinObjFolders &&
(e.Path.Contains("bin") ||
e.Path.Contains("obj")))
continue;
//Do a bunch of things
}
So basically, if !includeBinObjFolders = true stop evaluating.
And in this example, you are using || to evaluate the first two conditions; and if one of them is true you will stop evaluation.
foreach (SvnStatusEventArgs e in results) //results being my Collection
{
if ((e.Path.Contains("bin") ||
e.Path.Contains("obj")) && !includeBinObjFolders)
continue;
//Do a bunch of things
}
I honestly don't think either would be noticably faster than the other. Oh, and as an aside, evaluation is left-to-right, and never right-to-left.

c# logic error in a while-loop entering condition

I have some weird logic stuff going on.
x=false;
This one does not work:
while (R2.TS("a") && R2.TL("b") && (s=R2.SL().Trim()).Length > 0)
{
x=true;
}
result: x=false;
This one does work:
while (R2.TS("a") && R2.TL("b"))
{
if((s=R2.SL().Trim()).Length > 0)
{
x=true;
}
}
result: x=true;
Also, maybe it helps to know that those functions return true only if executed in right order, like R2.TS("a") then R2.TL("b") and then ((s=R2.SL().Trim()).Length > 0).
input is the same, but something is surely wrong here. Any ideas ?
thanks in advance.
Yes, the loops do two different things.
I think you mean a logic error, not a syntax error. Syntax error means it won't compile. Logic error means it doesn't do what you expect.
The first one will terminate if the R2.SL() expression is false. At least the first time round, (s=R2.SL().Trim()).Length > 0 must necessarily be false, so loop 1 terminates and x is never set to true. That is the only way you would get a difference between your two loops, all other conditions being the same.
In loop 2, intermediate values for R2.SL() isn't a problem, provided the other loop conditions remain true. When (s=R2.SL().Trim()).Length > 0 evaluates to true, x will be set.
Use the debugger luke. There is little point us trying to work out why this doesn't give you the result you want. It is better for you to work that out with some help. Click on the first line and push F9. It should turn red. Run your program and it will stop at this line. You can then hover over different variables to see which ones have which values. Then push F11 to step forward through your program.
In the first case have three conditions to which R2 has to comply namely
R2.TS("a") AND R2.TL("b") AND (s=R2.SL().Trim()).Length > 0), before you will enter the loop and return the value of x
In the 2nd case you only have two conditions to which R2 has to comply namely
R2.TS("a") AND R2.TL("b") and after the loop is entered, you have a new condition before the x value is returned.
They probably both work, but in the first case, you don't supply data which complies to the requirements of the loop.
It may be connected with && and || operations. They are shortaned. It means, that operations are looked continuously utill the first false occurs in the condition.
Because of shortaned operations you get 2 different cycles, which have different logics. Use the 2 cycle type. It's more correct.

How to stop execution of a while loop's condition, if the condition fails

I've got a while-loop, with a loop condition like so:
while (i != repetitionString.Length || !repetitionString[i].Equals(')'))
The first part of the condition checks to see that the end of the collection is not reached. Is it possible to not execute the part following || after the left side's condition is not met? The reason behind this is that if the left side's condition is not met, then this means that the collection is out of bounds, and hence the right side's evaluation/checking will throw an exception.
Is it possible to do this?
you just simply use && instead of ||. Since the right condition is supposed to be checked only if the first one has returned true.
This is what will happen anyway - the boolean condition on the right is only ever executed if the left one evaluates to false. You can force the right one to execute as well by using binary logic ( single |), but that is exactly not what you want to do, so your current statement will execute just fine.
It looks like what you really want is:
while (i < repetitionString.Length && repetitionString[i]!=")")
{
}
Short circuiting is already occurring.
My guess is that repetitionString is a zero-based index, while the .Length returns the total count. So you'll want to modify the if to stay in bounds:
while (i != (repetitionString.Length - 1) || !repetitionString[i].Equals(')'))
This looks equivalent to:
if (attribute != null || attribute.value != null)
because you can't use
if (attribute.value != null)
as this will raise an error when attribute == null, so I think your code is correct?
When the condition
i != repetitionString.Length
is met, the code will skip the part after the ||
Because it is an OR expression, there's no need to check the 2nd part of the condition when the first part of the condition returns true.
When you use && instead of ||, both conditions will always be checked. This is not what you want to do here.

need explanation, binary operator | working with boolean types?

I'm reading an source code, I found a statement like this:
if (Char.IsWhiteSpace(text[i]) | GetSpecialChars.Contains(text[i]))
Initially,I thought it was typo,instead || (or) operator. But for my surprise, it was compiled. how to it's possible? is | equivalent to || with boolean types?
Thanks in advance.
I'd suggest that it probably is a typo, though it will still work.
The reason boolean | is so rarely seen is that:
Much of the time || is the only one that is correct. If the expression on the right hand side would throw if the expression on the left-hand was true such as in x == null || x.Length == 0 which would successfully return true for a null or zero-length string or array while x == null | x.Length == 0 which would throw an exception for a null string or array as the Length property would still be examined.
Most of the rest of the time || will be faster. It might be nothing but a couple of clock cycles faster (though it could also be more if the expression on the rhs is expensive), but it hardly counts as a premature optimisation that we're all in the habit of using that form. (Just how much effort you put into deciding which goes on the left and which on the right may be another matter).
Some constructs that use it by one-line fans are rather unclear as far as readabilty goes.
The example in the question falls under point two. The only effect of | rather than || here in practice is a few nanoseconds of waste. Not that it matters, but it does lead to || being the habit to fall into.
(If on the other hand a property called GetSpecialChars or a method called Contains has a side-effect that means it has to be called, that property really needs to be renamed to make it clearer!).
About the only time it's useful is either because we really need some side-effect of the right-hand expression to take place, or in the assignment form based on it, |=.
In the former case, it's always worth considering an alternative of evaluating both expressions in separate statements and then ORing the result afterwards, to make it clearer that you care about the side-effect as well as the result.
In the latter case, it can make for more readable code, or at least to code that's more readable to some people! But many find it obscures things.
|| is the short-circuiting version of |. In your if statement, the GetSpecialChars.Contains method will be executed even if the character is white space, whereas || would halt evaluation and not execute the right side.
There is no mistake, this is a boolean OR operator, as opposed to the OR ELSE operator represented by ||. The difference is that the regular OR does not short-circuit, while OR ELSE does.
In your specific case, GetSpecialChars.Contains(text[i]) will be called even if Char.IsWhiteSpace(text[i]) returns true. If you replace | with ||, this would no longer happen (i.e. GetSpecialChars.Contains(text[i]) will not get called if Char.IsWhiteSpace(text[i]) is true).
The | operator in general has two meanings as used with integrals and used with booleans. In the first case it calculates the bit-wise OR of the integrals whereas in the latter case it calculates the logical OR when used with boolean values.
The second case (the logical-OR case) brings another two meanings:
"|" calculates the logical OR with the restriction that it evaluates both values i.e. x | y == false if and only if both x and y are false.
"||" does the same thing but only evaluates the second operand if necessary. So in the former example x || y would evaluate to true as soon as x is evaluated to true without looking at y.
You can refer directly to the MSDN documentation for that here and here
Hope this helps.

Categories

Resources