Reputation: 23
I am trying to understand whether a specific switch
statement is equivalent to this if
statement.
if (killstreak == 1) //If killstreak is 1, give one throwing knife and write Mr. Kniferino on screen.
{
attacker.GiveWeapon("throwingknife_mp");
attacker.Call("iprintlnBold", "^2Mr. Kniferino");
attacker.SetPerk("specialty_scavenger", true, false);
}
if (killstreak == 2) //If killstreak is 3, give 10 bullets and write You've received 10 bullets on screen.
{
attacker.Call("setweaponammoclip", "iw5_fnfiveseven_mp_tactical", 8);
attacker.Call("setweaponammostock", "iw5_fnfiveseven_mp_tactical", 0);
attacker.Call("iprintlnBold", "^2You've received 10 ^1bullets");
}
if (killstreak == 3) //If killstreak is 2, give Scavenger and write Scavenger on screen.
{
AfterDelay(10, () =>
attacker.SetPerk("specialty_scavenger", true, true));
attacker.Call("iprintlnBold", "^4Scavenger");
}
So would this if
statement be equivalent to this switch
statement?
switch (killstreak)
{
case 1:
attacker.GiveWeapon("throwingknife_mp");
attacker.Call("iprintlnBold", "^2Mr. Kniferino");
attacker.SetPerk("specialty_scavenger", true, false);
break;
case 2:
attacker.Call("setweaponammoclip", "iw5_fnfiveseven_mp_tactical", 8);
attacker.Call("setweaponammostock", "iw5_fnfiveseven_mp_tactical", 0);
attacker.Call("iprintlnBold", "^2You've received 10 ^1bullets");
break;
case 3:
AfterDelay(10, () =>
attacker.SetPerk("specialty_scavenger", true, true));
attacker.Call("iprintlnBold", "^4Scavenger");
break;
}
If something isn't clear, I'll happily explain again.
Upvotes: 0
Views: 146
Reputation: 5059
Functionally, yes, it's the same, given that 1 can never equal 2 or 3. killstreak is always going to be equal to one of those and not the others.
But logically, the construction you've made here differs in an important way. switch statements in C# are more identical to if/else-if/else (with default) than they are to if/if/if. break
prevents the control flow from passing any further upon the first time you encounter a case that evaluates to true, whereas every single one of your if statements will always be evaluated.
For example, if you accidentally hit the wrong key when constructing your second conditional:
if (killstreak == 1)
{
FunctionOne();
}
// should have been 2
if (killstreak == 1)
{
FunctionTwo();
}
both FunctionOne() and FunctionTwo() would execute, because those two conditionals are logically independent of one another. The result of one has no bearing on whether the next is executed.
(Edit: it's been pointed out that there's not really a way at all to have two identical cases in switch statements. They require either literals or constants, and will fail to compile if the same value is used for multiple cases. I've removed that portion.)
An easy way to deal with this in terms of if blocks where you only ever want one portion of code to execute is using else if:
if (killstreak == 1)
{
FunctionOne();
}
else if (killstreak == 1)
{
FunctionTwo();
}
This would execute identically to the example switch statement above - only FunctionOne() would ever be executed. Your typo no longer causes two separate killstreak actions to execute each time the user gets a single kill.
Edit: Namfuak points out another possibility - if somehow killstreak was incremented within FunctionOne(), when execution came to the second if block below, FunctionTwo() would also execute.
// killstreak is 1
if (killstreak == 1)
{
// will execute
FunctionOne(); // increments killstreak
}
// killstreak is 2
if (killstreak == 2)
{
// will also execute
FunctionTwo();
}
Upvotes: 1
Reputation: 55760
Almost, but not quite. The outcome in your case will be the same (so you could say that they are different ways of achieving the same logic). The difference is that your if
statement tests would all be executed, while the switch would only evaluate once, than branch to the appropriate case.
You could add else
statements to terminate early but still there is a fundamental difference between switch
statements and if/else
chains. The latter give you more flexibility, while the switch
could technically, be optimized by the compiler into a branch table, and the condition (if it's an expression) will only be evaluated once.
This would be more like a switch statement but still, not exactly the same:
if (killstreak == 1)
{
/* case 1 */
}
else if (killstreak == 2) // only tested if killstreak != 1
{
/* case 2 */
}
else if (killstreak == 3) // only tested if killstreak != 1 and != 2
{
/* case 3 */
}
But as I said, this is still not entirely the same. A switch statement may be translated by the compiler into equivalent code to the if/else
chain above, but it could be translated into a lookup table too, something more like this:
BranchTable = [CASE1_ADDR, CASE2_ADDR, CASE3_ADDR]
goto BranchTable[killstreak]
CASE1_ADDR:
/* code for test 1*/
goto AFTER_SWITCH_ADDR;
CASE2_ADDR:
/* code for test 2*/
goto AFTER_SWITCH_ADDR;
CASE3_ADDR:
/* code for test 3*/
AFTER_SWITCH_ADDR:
/* code following swtich statement */
Upvotes: 4