Ternary vs Chained If-else-if (Performance) - c#

I did the due-diligence to see if this has been asked before and didn't find anything identical but close, so here goes.
Say I have a chain of if-else-if statements.
foreach (value in valueList)
if (value == 120) {
w = true;
} else if (value == 140) {
x = true;
} else if (value == 160) {
y = true;
} else if (value == 180) {
z = true;
}
}
Is there any advantage of changing the else-if chain to ternary expressions such as:
foreach (value in valueList) {
w = (value == 120) ? true : false;
x = (value == 140) ? true : false;
y = (value == 160) ? true : false;
z = (value == 180) ? true : false;
}
My first inclination is no. Because of the for loop every assignment is made each time the loop happens. Whereas in the if-else-if chain, the assignment is made only once. But the comparisons are made more often (right?). Can anybody settle this for me?
I know a switch would easily defeat the both in terms of performance. Can I base this question on the assumption that using switch is not an option?
I guess another question inside this question would be what are the Big-O comparisons between the two?

Note that both solutions are very different. The first one only assigns true to one of those four variables while the other one will overwrite whatever value all four of them had before.
That being said, using the ternary operator in the second code is really bad. You can just assign the result of the comparison directly:
w = value == 120;
x = value == 140;
y = value == 160;
z = value == 180;
Taking aside the semantics, this will also make it likely a bit more performant than a if/else structure. You might think that just running a single comparison will make it faster, so the first solution should be better, but in fact, branching can be slow. And since comparison operations are actually really fast, just assigning the result of a comparison four times is likely “faster”.
Note that none of this will actually have any real performance impact. Both is very low-level and it’s very likely that you have something else in your application’s code that is way slower, being a likelier bottle neck. So I wouldn’t stress about using one or another way for performance here; just choose what is semantically correct and then use whatever solution makes the semantics as clear as possible.
I know a switch would easily defeat the both in terms of performance.
A switch statement gives you the same effect as a chain of ifs and elses, so there isn’t really a difference here.
I guess another question inside this question would be what are the Big-O comparisons between the two?
Both is linear, as you just loop through the list. Every other difference is constant, so it doesn’t matter in Big-O notation.

The two function entirely differently. Performance is irrelevant; they don't do the same thing.
The first snippet sets the appropriate variable to true if the condition is met, and does nothing if the corresponding condition isn't met, meaning it leaves the original value.
The second snippet assigns a value to each variable on each iteration.
So the first snippet is effectively asking, "is any value equal to this number" for each of the numbers, the second snippet is effectively asking, "is the last value equal to this number" for each of the numbers. I assume you intend the former, not the latter, so the latter is simply wrong.

Well, in the case of integers, I really like to use a switch when I have too many cases. #ima explains it in this answer. Otherwise, it only matters what looks better or more "readable"
However using a switch with strings is a totally different story as explained in this post.

Related

If Statement with Multiple Conditions vs Individual If Statements [duplicate]

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.

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.

if(value == null) vs if(null == value) [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why does one often see “null != variable” instead of “variable != null” in C#?
This is more a curiosity question, is there any performance difference between the statement.
if(value == null)
and
if(null == value)
is it noticeable, I use c#, PHP & javascript quite often and I remember someone saying if(null == value) was faster, but is it really?
I will soon be starting development on an application that will parse huge quantities of data in the region of Terabytes so even if the performance gain is in the millisecond range it could have an impact. Anyone have any ideas?
I doubt that there's a measurable performance advantage either way. I'll bet the person who told you this didn't have any hard data.
As far as I know, it's a historical artifact, a technique from C and C++ to guard against this mistake:
if (c = null) {
}
The compiler will catch this if you reverse the arguments, since you can't assign something to null.
I profiled both over 100 million iterations.
if(value == null)
-- 6.85175704956 seconds (68.5 nano-seconds each)
if(null == value)
-- 6.75543808937 seconds (67.5 nano-seconds each)
So it's up to you if 1 nanosecond is enough of a gain.
There is absolutely no performance difference to be expected.
The only reason the (ugly) form (if null == value) is used is to avoid a C/C++ specific typo:
if (value = null) // compiles but _assigns_ null to value and always returns false
... // never executed
I think it's fair to expect there will be no difference: it's such a simple case that if there was a difference the compiler would make sure to generate the fastest version anyway.
Yes I also think there will be no difference, but personally I prefer if(value == null)
Optimizations like this will gain you a clock cycle at best (I wouldn't know why though). But most likely if it is any better, then the compiler will optimize it for you.
The reason to put any literal (such as null) first is that you can not accidentally assign the value if you do = instead of ==. I personally do find it less readable though.
I'm not sure if it's faster or not but some languages allow you to assign in an if statement without warning you so if you do:
if (value = null) by mistake you could wipe your variable, whereas the other way around wouldn't cause weird issues further on down the execution path.

Changing variables outside of Scope C#

I'm a beginner C# programmer, and to improve my skills I decided to give Project Euler a try. The first problem on the site asks you to find the sum of all the multiples of 3 and 5 under 1000. Since I'm essentially doing the same thing twice, I made a method to multiply a base number incrementally, and add the sum of all the answers togethor.
public static int SumOfMultiplication(int Base, int limit)
{
bool Escape = false;
for (int mult = 1; Escape == true; mult++)
{
int Number = 0;
int iSum = 0;
Number = Base * mult;
if (Number > limit)
return iSum;
else
iSum = iSum + Number;
}
regardless of what I put in for both parameters, it ALWAYS returns zero. I'm 99% sure it has something to do with the scope of the variables, but I have no clue how to fix it. All help is appreciated.
Thanks in advance,
Sam
Your loop never actually executes:
bool Escape = false;
for (int mult = 1; Escape == true; mult++)
Escape is set to false initially, so the first test fails (Escape == true returns false) and the body of the loop is skipped.
The compiler would have told you if you were trying to access variables outside of their defined scope, so that's not the problem. You are also missing a return statement, but that is probably a typo.
I would also note that your code never checks if the number to be added to the sum is actually a multiple of 3 or 5. There are other issues as well (for example, iSum is declared inside of the loop and initialized to 0 after each iteration), but I'll let you work that one out since this is practice. The debugger is your friend in cases like these :)
EDIT: If you need help with the actual logic I'll be happy to help, but I figure you want to work it out on your own if possible.
As others have pointed out, the problem is that the control flow does not do what you think it does. This is a common beginner problem.
My suggestion to you is learn how to use your debugger. Beginners often have this strange idea that they're not allowed to use tools to solve their coding problems; that rather, they have to reason out the defect in the program by simply reading it. Once the programs become more than a page long, that becomes impossible for humans. The debugger is your best friend, so get to know its features really well.
In this case if you'd stepped through the code in the debugger you'd see that the loop condition was being evaluated and then the loop was being skipped. At that point you wouldn't be asking "why does this return zero?", you'd be asking "why is the loop body always skipped?" Clearly that is a much more productive question to ask since that is actually the problem here.
Don't write any code without stepping through it in the debugger. Watch every variable, watch how it changes value (the debugger highlights variables in the watch windows right after they change value, by the way) and make sure that the control flow and the variable changes are exactly as you'd expect. Pay attention to quiet doubts; if anything seems out of the ordinary, track it down, and either learn why it is correct, or fix it until it is.
Regarding the actual problem: remember that 15, 30, 45, 60... are all multiples of both three and five, but you only want to add them to the sum once. My advice when solving Project Euler problems is to write code that is as like what you are trying to solve as is possible. Try writing the problem out in "pseudocode" first. I'd pseudocode this as:
sum = 0
for each positive number under 1000:
if number is multiple of three or five then:
add number to sum
Once you have that pseudocode you can notice its subtleties. Like, is 1000 included? Does the problem say "under 1000" or "up to 1000"? Make sure your loop condition considers that. And so on.
The closer the program reads like the problem actually being solved, the more likely it is to be correct.
It does not enter for loop because for condition is false.
Escape == true
returns false
Advice:
Using for loop is much simpler if you use condition as limit for breaking loop
for (int mult = 1; something < limit; mult++)
This way in most cases you do not need to check condition in loop
Most programming languages have have operator modulo division.
http://en.wikipedia.org/wiki/Modulo_operation
It might come handy whit this problem.
There are several problems with this code. The first, and most important, is that you are using the Escape variable only once. It is never set to false within your for loop, so it serves no purpose whatsoever. It should be removed. Second, isum is declared within your for loop, which means it will keep being re-initialized to 0 every time the loop executes. This means you will only get the last multiple, not the addition of all multiples. Here is a corrected code sample:
int iSum = 0;
for(int mult = 1; true; mult++)
{
int Number = Base * mult;
if(Number > limit)
return iSum;
else
iSum += Number;
}

When to use 'if…else if' and when to use

1) I know how if…else if statements work, but in the next example both methods are identical as far as the resulting value is concerned. So does it matter which of the two methods I use or should I always go for one that is semantically closest to what the code is trying to do ( here I’m guessing that semantically the two methods are quite different )? So which method would you use and why?
protected string GetNumberDescription(int value)
{
if (value >= veryBigNumber)
return veryBigNumberDescription;
else if (value >= bigNumber)
return bigNumberDescription;
else if (value >= smallNumber)
return smallNumberDescription;
else
return "";
}
protected string GetNumberDescription(int value)
{
if (value >= veryBigNumber)
return veryBigNumberDescription;
if (value >= bigNumber)
return bigNumberDescription;
if (value >= smallNumber)
return smallNumberDescription;
else
return "";
}
2) I noticed losts of code uses the following format when writting if ... else if statements:
if ...
else if ...
else ...
But isn't ( at least conceptually ) more correct way:
if ...
else
if ...
else ...
You should probably use the first. It's more accepted, and more logical. (You don't care about anything afterwards if this condition is true... indicate that in your code.)
It's generally more accepted, and more compact and readable, to use the first way (else if). Python even has a specific keyword for it (elif).
I personally would use
protected string GetNumberDescription(int value)
{
if (value >= veryBigNumber)
return veryBigNumberDescription;
if (value >= bigNumber)
return bigNumberDescription;
if (value >= smallNumber)
return smallNumberDescription;
return string.Empty;
}
It really all depends on what your function is doing. If its simple like this then keep it simple. If you might need to do something with the result before you return it then I'd use Egrunin's solution
protected string GetNumberDescription(int value)
{
string ret = "";
if (value >= veryBigNumber)
ret = veryBigNumberDescription;
else if (value >= bigNumber)
ret = bigNumberDescription;
else if (value >= smallNumber)
ret = smallNumberDescription;
return ret;
}
The question is already answered, but I added this because:
There are advantages to having a single exit from a function.
The same variable is being tested repeatedly, so the if/elseif is most appropriate.
Edited to add:
I'm usually a big fan of exiting a function early in cases like this:
if (conditionOne)
{
if (conditionTwo)
{
if (conditionThree)
{
interesting_stuff();
}
}
else
boring();
}
return;
I'm much happier seeing this:
if (!conditionOne)
return;
if (!conditionTwo)
{
boring();
return;
}
if (!conditionThree)
return;
interesting_stuff();
return;
But when there are exits at many different nesting levels, it's too easy to miss one as you're reading over the code.
Also, as mentioned in the comments: a single exit means only one place to put a breakpoint.
If the conditions are mutually exclusive then I think an else if pattern is best. It will be harder to accidentally break as the code evolves and becomes more complex, because your control flow more accurately represents the mutual exclusiveness of the logic.
Consider if someone re-factored your first example to be similar to egrunin's example such that there is only one return, but consider they forgot to add the "else" to each if:
protected string GetNumberDescription(int value)
{
string ret = "";
if (value >= veryBigNumber)
ret = veryBigNumberDescription;
if (value >= bigNumber)
ret = bigNumberDescription;
if (value >= smallNumber)
ret = smallNumberDescription;
// BUG: very big numbers still fall through to this last condition,
// because they meet all conditions
return ret;
}
They have just introduced a bug. They may not have realized that the returns were part of the logic being expressed. While the error is obvious here, in real life this code a couple years down the road could potentially become more complex, lengthy, and more difficult to read such that it's easier to make such a mistake.
Detecting Unexpected Bug
Additionally, if at least one condition must be met(i.e. should never return an empty string), then I'd throw an exception in the final else if you are assuming all cases should be handled. This would detect a bug in the code where the code fell through all the elses and did not find a matching condition. If you do not throw an exception, then the bug might cause strange behavior. How will the rest of the code handle the uninitialized empty string? Depends largely on the code at hand. The idea of throwing an exception is to cause a hard failure exactly where the bug is so that it can be easily identified and corrected, instead of allowing the application to continue running with an invalid return.
if (value >= smallNumber)
ret = smallNumberDescription;
else if(...)
ret = otherNumberDescription;
else
throw new InvalidOperationException($"No condition matched for value={value}");
return ret;
If paired with appropriate exception logging/notifications, then this would allow you to become aware of this bug and add a condition to handle unanticipated values. Not really necessary for very simple conditions, but very helpful in proactively finding and correcting bugs in this kind of code.
They are semantically identical. I doubt there is any difference in performance, so the choice is about style and readability. If you're curious, compile the above code into an assembly and use Reflector to see if there is any difference in the IL. My guess is there would be little difference if any.
It's mostly a matter of preference. when using return statements, you don't need the elses in my opinion, since it's clear that the function ends right there. It's all very situation and style dependent, so there is no clear 'best' way to do it.
I would suggest the former, as you are making a logical choice between four possibilities. You are grouping the decision in one if/else if block.
If you separate out the decisions like in your second function, they appear to not be connected at all. Clearly they are, as the value variable is repeated, but it might not necessarily be obvious.
Additionally, when you've got nothing to return, please return null, and not a blank string. In an application I maintain, it is still necessary to use if (value == null || value != "").
You want to use "else if" because that only will fire if the first "if" is not accepted. In your case the 3 if statements are okay, simply because if a latter "if" is correct, then the previous "if"s cannot be.
In a case where all of your if statements could be correct, you'd want to use else if.
For Example:
if (8<10) {
return 10;
}
if (8<9) {
return 9;
}
That's a very simplistic example, but you get the idea. You use "else if" when you want only one "if" statement to fire.
I would use the first option, as it shows in code the comparisons are "grouped" some. For 2 I think they end up in exactly the same IL code.
I always make sure the most common senario is first in the if..else statement, as that is best for performance.
The alternatives are pretty close semantically, so it doesn't matter that much. As suggested in some answers, putting the result in a string variable and return at the end might better represent what you are doing in the method.
Another alternative is to use the conditional operand, which gives you a less verbose code:
protected string GetNumberDescription(int value) {
return
value >= veryBigNumber ? veryBigNumberDescription :
value >= bigNumber ? bigNumberDescription :
value >= smallNumber ? smallNumberDescription :
String.Empty;
}
With the return statements, it really doesn't matter. I totally disagree with those who say the second is in any way worse, though. What makes it worse?
In response to your second question: you are quite right. In fact, not only are the two ways of formatting if/else if effectively the same; they actually are literally the same. C# does not enforce a particular formatting style, so these are all identical:
// This...
if (A())
return "Congrats!";
else if (B())
return "Not bad!";
else if (C())
return "Next time...";
else
return "Uh-oh.";
// ...is the same as this...
if (A())
return "Congrats!";
else
if (B())
return "Not bad!";
else
if (C())
return "Next time...";
else
return "Uh-oh.";
// ...which is the same as this...
if (A()) return "Congrats!"; else
if (B())
return "Not bad!";
else
{ if
(C())
return
"Next time...";else{
return "Oh-oh.";
}}
protected string GetNumberDescription(int value)
{
return new NumberDescriptor(value).toString();
}
All you need is to hide your logic.
Don't take this too serious, but...i would do it that way. I know, your question is not anserwed here, but there are already enough if/then/else examples in this topic.
1) The first one is more prevalent and in common practice. So it would be wise to stick to the standard practice.
2) Generally when we have more than one conditional statement, else if is used in the intermediate conditional outputs and else is used in the last conditional output. Moreover it might be more efficient as I believe it does not have to check the same condition everytime unlike the if-else-if-else... type.
Its more like a choice provided to you where you find your own out of many paths going to the same destination. But the choice that you hear or see often is the one that is popular because of experience of many users and experts.
I would say to use the first if the function is thought of as returning one of four possibilities, all of which are considered "successful". I would use the latter style if some returns denoted "failures". For example (toy example--throwing might be better for the error cases):
string get_suit_name(int suit)
{
string suit_names[4] = {"clubs", "diamonds", "hearts", "spades"};
if (0 > suit) /* Avoid LT sign */
return "Suit is improperly negative!";
if (suit >= 4)
return "Suit is too big!";
return suit_names[suit];
}
Well from my point of view it would be these priorities from highest to lowest.
Functionality / achieving the end goal
Reduction of cost in any scope/level
Readability
^^^^ note that many will dispute this on my list and call readability above reduction of cost, it really depends on your work envi. and the end goal but I find this the most common. But guess coming from a rookie that doesn't mean much huh :D
After that you it's pretty much peanuts. Same goes for ? : operator. If you are convinced it's more readable, go for it. Function wise it doesn't really matter. But if(){}else{} is significantly different from if(){}else if(){} So pick what's the optimum code (Highest wanted results minus unexpected results - 0.5* readability score ) pretty much what I'd go on.
Now seeing as the code does the same for you, a new attribute comes into play, will this code be edited at some later stage? And if so what would be best to go for then? Don't forget the future of the code, nor the comments, that a free bonus to pick along with it. You can even do both if you can't figure it out for the time and just comment the other but that does leave sloppy walls of text to be removed later on cleanup/release.
For the example provided, you don't need to worry about "if" statements if you're willing to sacrifice a ton of readability and possibly a little speed:
string [] descriptions = {"", smallNumberDescription, bigNumberDescription, veryBigNumberDescription};
protected string GetNumberDescription(int value)
{
int index = Convert.ToInt32(value >= smallNumber) + Convert.ToInt32(value >= bigNumber)
+ Convert.ToInt32(value >= veryBigNumber);
return descriptions[index];
}
In terms of performance, they may be the same depending on the compiler/interpreter. In my opinion the second one is better....much easier to debug.
Well, in your particular case, I would suggest this:
protected string GetNumberDescription(int value) {
if (value >= veryBigNumber)
return veryBigNumberDescription;
if (value >= bigNumber)
return bigNumberDescription;
if (value >= smallNumber)
return smallNumberDescription;
return "";
}
Since, you are returning from the function on any of the true condition, there is no need to use 'else if'. In your case, if any of the conditions become true, the code won't execute further.
Also, the last 'else' is not required, for the control will reach that point only when all the above conditions have been false.
It's all a matter of where you're using it, and how. The main motive is to maximize the readability of your code and make it as elegant and easy-to-understand as possible.
Many would prefer the first way since it indicates in your code that you don't care what happens as soon as a condition is satisfied.

Categories

Resources