I've come up with a little trick to store all 8 possible situations into one single integer value:
switch ((a == 1 ? 1 : 0) + (b == 1 ? 2 : 0) + (c == 1 ? 4 : 0))
{
case 0: break;
//none true
case 1: break;
//a true
case 2: break;
//b true
case 3: break;
//a and b true
case 4: break;
//c true
case 5: break;
//a and c true
case 6: break;
//b and c true
case 7: break;
//all true
}
The mathematical formula for each variable:
- n: numeral system base [2, ∞]
- m: zero-based index of the checked variable [0, ∞]
- v: zero-based index of the variable's value [0, n - 1]
result for one variable = nm * v
As an example, 3 ternary variables:
int
situation = (a == 0 ? 0 : (a == 1 ? 1 : 2)) + (b == 0 ? 0 : (b == 1 ? 3 : 6)) +
(c == 0 ? 0 : (c == 1 ? 9 : 18));
The switch above has to (in every case) get-and-check 4 times (3 times in the
calculation, 1 time to match a case). However, it also has to perform the
addition.
So, is switch in this case faster? I have tested switch's performance (every
single situation 100,000,000 times) against the following if-else if trees:
1. The obvious one:
if (a == 1 && b == 1 && c == 1) ;
else if (a == 1
&& b == 1) ;
else if (a == 1
&& c == 1) ;
else if (b == 1
&& c == 1) ;
else if (a == 1)
;
else if (b == 1)
;
else if (c == 1)
;
else ;
| Condition | Num of checks | Check sequence |
| a & b & c | 3 | a,b,c |
| a & b | 5 | a,b,c,a,b |
| a & c | 6 | a,b,a,b,a,c |
| b & c | 5 | a,a,a,b,c |
| a | 8 | a,b,a,b,a,c,a |
| b | 8 | a,a,a,b,c,a,b |
| c | 8 | a,a,a,b,a,b,c |
| none | 8 | a,a,a,b,a,b, |
Average: 6.375 checks
Switch/if-tree ratio:
- calculation into a variable first: 9/10
- calculation straight into switch: 3/4
Switch is faster.
My testing code:
int
counter = 0;
Timer
timer = new Timer(1);
timer.Elapsed += (object
o, ElapsedEventArgs e) =>
{
++counter;
};
timer.Start();
for
(int i = 0; i < 100000000; ++i)
{
for (int a = 0; a < 2; ++a)
{
for (int b = 0;
b < 2; ++b)
{
for (int c = 0;
c < 2; ++c)
{
if (a == 1 && b == 1 && c == 1) ;
else if (a == 1
&& b == 1) ;
else if (a == 1
&& c == 1) ;
else if (b == 1
&& c == 1) ;
else if (a == 1)
;
else if (b == 1)
;
else if (c == 1)
;
else ;
}
}
}
}
timer.Stop();
Console.WriteLine(counter.ToString());

FireMystPosted Feb 6, 2014, 1:44 AM
This is a good article. I like how you laid out the code, It would be better too if you did benchmark tests against all three constructs like this blog: http://cc.davelozinski.com/c-sharp/what-is-the-fastest-conditional-statement I've personally found the nested switch/case statements slower than their if/else equivalents.
lgsalamonPosted Oct 7, 2010, 10:52 AM
try this : static void newswitchtest() { Stopwatch timer; timer = Stopwatch.StartNew(); timer.Stop(); int bin; timer.Start(); for (int i = 0; i < 100000000; ++i) { for (int a = 0; a < 2; ++a) { for (int b = 0; b < 2; ++b) { for (int c = 0; c < 2; ++c) { bin = a + (b << 1) + (c << 2); switch (bin) { case 0: break; case 1: break; case 2: break; case 3: break; case 4: break; case 5: break; case 6: break; case 7: break; } } } } } timer.Stop(); Console.WriteLine(timer.ElapsedMilliseconds.ToString()); } My tests : 9704 ms if/else 8251 ms switch 5817 ms the code above Good article.
Sam HobbsPosted Sep 28, 2010, 5:56 PM
Another possibility would be to create an array of methods using a delegate type and then instead of using a switch, just index into the array. That could be quite efficient if there are more than 3 conditions, right?