user3713606
user3713606

Reputation: 23

Is switch statement the same as if statement in this specific code?

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

Answers (2)

furkle
furkle

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

Mike Dinescu
Mike Dinescu

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

Related Questions