我试图了解特定switch
语句是否等同于此if
语句。
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");
}
那么这个if
语句是否等同于这个switch
语句?
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;
}
如果事情不明确,我会很高兴再次解释。
答案 0 :(得分:4)
几乎,但不完全。您案例中的结果将是相同的(因此您可以说它们是实现相同逻辑的不同方式)。不同之处在于,您的if
语句测试都将被执行,而交换机只会评估一次,而不是分支到相应的案例。
您可以添加else
语句以提前终止,但switch
语句和if/else
链之间仍存在根本区别。后者为您提供了更大的灵活性,而switch
在技术上可以由编译器优化到分支表中,条件(如果它是表达式)只会被评估一次。
这将更像一个switch语句,但仍然不完全相同:
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 */
}
但正如我所说,这仍然不完全相同。 switch语句可以由编译器转换为上面的if/else
链的等效代码,但也可以将其转换为查找表,更像是这样:
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 */
答案 1 :(得分:1)
功能上,是的,它是相同的,因为1永远不能等于2或3. killstreak总是等于其中一个而不是其他的。
但从逻辑上讲,你在这里建造的建筑在很大程度上是不同的。 C#中的switch语句与if / else-if / else(默认值)比if / if / if更相同。 break
会在第一次遇到计算结果为true的情况时阻止控制流进一步传递,而每个if语句都会被评估。
例如,如果您在构建第二个条件时意外碰到了错误的键:
if (killstreak == 1)
{
FunctionOne();
}
// should have been 2
if (killstreak == 1)
{
FunctionTwo();
}
FunctionOne()和FunctionTwo()都会执行,因为这两个条件在逻辑上彼此独立。一个人的结果与下一个是否被执行无关。
(编辑:有人指出,在switch语句中有两个相同的情况根本不是一种方法。它们需要文字或常量,如果相同则无法编译值用于多个案例。我已删除该部分。)
根据if中只需要执行一部分代码的块来处理这个问题的简单方法是使用else if:
if (killstreak == 1)
{
FunctionOne();
}
else if (killstreak == 1)
{
FunctionTwo();
}
这将与上面的示例switch语句完全相同 - 只执行FunctionOne()。每次用户获得一次杀戮时,您的拼写错误不再导致两个单独的killstreak操作执行。
编辑:Namfuak指出另一种可能性 - 如果某种方式killstreak在FunctionOne()内增加,当执行到下面的第二个if块时,FunctionTwo()也会执行。
// killstreak is 1
if (killstreak == 1)
{
// will execute
FunctionOne(); // increments killstreak
}
// killstreak is 2
if (killstreak == 2)
{
// will also execute
FunctionTwo();
}