I am using a switch and get a warning that code is unreachable.
If control goes to case 2 or 3, something will get execute then what is the issue?
While executing case "2" and case "3", your function pointer will never reach break statement because of goto statements in if..else conditions.
It is unreachable, the if statement above it will always redirect with the gotos.
You could just refactor the logic into a simple if statement..
var cemValIsOne = hdnCEMStatus.Value == "1";
var cemIDIsZeroOrEmpty = hdmCEMID.Value == "" || hdmCEMID.Value == "0";
if(cemValIsOne || (!cemValIsOne && !cemIDIsZeroOrEmpty))
{
// case 1 code...
}
else
{
// case 0 true if statement code
}
Related
I have the following while statement -
while ((!testString.Contains("hello")) && (NewCount != OldCount) && (attemptCount < 100))
{
//do stuff (steps out too early)
}
This is stepping out of the statement even though all the conditions have not been met.
I have tried to reduce it like -
while (!testString.Contains("hello"))
{
// this works and steps out when it should
}
And this steps out when hello is present for example. I also tried changing this to an OR statement which reversed the problem to never stepping out the statement.
Addint the && (NewCount != OldCount) && (attemptCount < 100)) conditions is causing this behaviour how can I resolve this?
This is stepping out of the statement even though all the conditions
have not been met.
To achieve that you need to specify logical OR (||).
For example:
while ((!testString.Contains("hello")) || (NewCount != OldCount) || (attemptCount < 100))
{
//while at least one those conditions is true, loop will work
}
Which means that inside loop you need to introduce security checks, where required, for conditions which are not more true, while loop is still executing.
As an addition to Tigran´s answer. Often (in order to avoid mess with the complex condition) it could be useful to push the condition into the loop:
while (true) { // loop forever unless:
if (testString.Contains("hello")) // ...test string contains "hello"
break;
if (NewCount == OldCount) // ...counts are equal
break;
if (attemptCount >= 100) // ... too many attempts
break;
// ...it's easy to add conditions (as well as comment them out) when you have them
// Loop body
}
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.
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 */
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();
}
This question already has answers here:
Break out of a while loop that contains a switch statement
(15 answers)
Closed 8 years ago.
I was asked to do maintenance work on some C# code which, I'm told, was originally converted from Visual Basic 6. (I mention this only because I don't know VB6 so I don't know if it would have made more sense in that language. . .)
It's got a for loop which parses some text for a proprietary scripting language by using a switch inside the for loop . . .
for ( t = 0; t < upperBound(tokens); t++)
{
String mystring = tokens[t];
switch (mystring)
{
case "GOTO":
if (firstGoto == -1)
{
firstGoto = t;
}
else
{
// compute number of tokens in GOTO
pointLength = t - firstGoto - 1;
break; // exit for
}
break;
case "ACTUATE"
. . .
Notice the comment
// exit for
The programmer expects the break will exit the for loop but I think it will only exit the switch statement because the documentation for break says
The break statement terminates the closest enclosing loop or switch statement in which it appears. Control is passed to the statement that follows the terminated statement, if any.
So am I correct that this will only exit the switch, but still be in the for, and if so, what is the correct way to do what the original programmer intended?
Yes, break will break out of the closest loop or switch. The easiest way is to use a goto. (No, goto is not evil)
for {
switch(...) {
....
goto MyLabel;
}
}
MyLabel:
Yes, you are correct... break will only exit the innermost block of code.
One easy way to do this is to also have a boolean flag which is set within the switch statement, and at the end of the loop just do this:
var flag = false;
for (...) {
switch (...) {
case "x":
flag = true;
}
if (flag) break;
}
Yes break will only terminate the switch in this scenario. How about using a boolean to exit the for as well..?
for ( t = 0; t < upperBound(tokens); t++)
{
String mystring = tokens[t];
bool exitFor = false;
switch (mystring)
{
case "GOTO":
if (firstGoto == -1)
{
firstGoto = t;
}
else
{
// compute number of tokens in GOTO
pointLength = t - firstGoto - 1;
exitFor = true;
break; // exit for
}
break;
case "ACTUATE"
. . .
if(exitFor)
break;
So I was making a Rock Paper Scissor game and I've sort of made adjustments to it to include life and other things. Now I got stuck with the switch statement. My if statement works fine:
private void Result_TextChanged(object sender, EventArgs e)
{
if (playerscore == 1 || pcscore == 1)
{
PlayerLife.Image = Properties.Resources.Five;
}
}
I was wondering how I could translate this to the switch statement?
private void Result_TextChanged(object sender, EventArgs e)
{
switch (playerscore || pcscore)
{
case 1:
PlayerLife.Image = Properties.Resources.Five;
break;
}
}
Doesn't seem to work.
The simple answer is No. You cant use it like that.
Switch works with single expression.
You may check MSDN for details.
You may try like this:-
if (playerscore == pcscore)
{
switch (playerscore)
{
case 1:
PlayerLife.Image = Properties.Resources.Five;
break;
}
}
EDIT:-
As commented by Jeppe Stig Nielsen in the comments, You can switch on any expression of a suitable type. That expression may contain ||. There can be many case labels associated with each switch section in a switch block.
But personally speaking that would not be a good practice to follow. You may try to use if statement for that.
You may try like this if you want:
switch (playerscore == 1 || pcscore == 1)
In C#, a switch statement resolves a single expression and compares that value with a list of possible cases:
switch(someExpression)
{
case x: // This runs if someExpression == x
break;
case y: // This runs if someExpression == y
break;
}
Now, you could switch on the expression (playerscore == 1 || pcscore == 1) like so:
switch(playerscore == 1 || pcscore == 1) // This expression is either true or false
{
case true: // Runs if playerscore is 1 or pcscore is 1
break;
case false: // runs if neither playscore or pcscore are 1
break;
}
However, the above is rather unreadable and silly. You'd be best off with the if statement:
if(playerscore == 1 || pcscore == 1)
{
// Runs if playerscore is 1 or pcscore is 1
}
else
{
// runs if neither playscore or pcscore are 1
}
You could write it like this but why would you want to?
switch (playerscore == 1 || pcscore == 1)
{
case true:
PlayerLife.Image = Properties.Resources.Five;
break;
default:
break;
}
As Jeppe points out in the comment below, when you use || or && you end up with a bool and an if statement should be used.
Here is a great answer by #EricLippert on what can be used as the expression in a swtich statement.
What you are trying to do doesn't make sense, if playerscore = 3 and pcscore = 2 then what would playerscore || pcscore be equal to?
If you have a whole bunch of variables, say not just two, but 5, 10, or even an unknown number, then what you can do is put all of the values that you want to compare to 1 into a collection and then act on that collection as a whole.
//this could just be a list/array accepted as a paramter,
//can include other variables, or whatever
var scores = new []{playerscore, pcscore};
if(scores.Any(score => score == 1))
PlayerLife.Image = Properties.Resources.Five;
switch isn't really an appropriate tool for manipulating collections like this.
This makes no sense: in a switch statement you always want to compare with a specific type, rather than to a boolean value as follows:
switch (playerscore || pcscore)
in your case use the 'if'-statement
Suppose that playerscore and pcscore are integer who has 0 or 1 as possible values
resp = playerscore + 10 * pcscore;
switch (resp)
{
case 0:
// both are false
break;
case 1:
// playerscore true
break;
case 10:
// pcscore true
break;
case 11:
// both are true
break;
default:
// error in input data
break;
}
This question already has answers here:
Control cannot fall through from one case label
(8 answers)
Closed 9 years ago.
I am trying to convert an if statement to switch cases (for readability)
1) I've read switch statements are aweful in general - Is that true?
https://stackoverflow.com/questions/6097513/switch-statement-inside-a-switch-statement-c
2) The statement goes like this:
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
break;
case Display.NonExpense:
if (expected.EXPENSE == true)
break;
case Display.All:
//Code
break;
}
Error is:
Control cannot fall through from one case label ('case 1:') to another
This is the original if statement:
if ((Show == Display.All) || (expected.EXPENSE == true && Show == Display.Expense) || (expected.EXPENSE == false && Show == Display.NonExpense))
{
//Code
}
First off, I notice that you forgot to ask a question in your second point. So I'm going to ask some questions for you addressing your second point:
What is the meaning of the "can't fall through" error?
Unlike C and C++, C# does not allow accidental fall-through from one switch section to another. Every switch section must have an "unreachable end point"; it should end with a break, goto, return, throw or (rarely) infinite loop.
This prevents the common bug of forgetting to put in the break and "falling through" accidentally.
You've written your code as though fall-through is legal; my guess is that you're a C programmer.
How can I force fall-through in C#?
Like this:
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
break;
else
goto case Display.All;
case Display.NonExpense:
if (expected.EXPENSE == true)
break;
else
goto case Display.All;
case Display.All:
//Code
break;
}
Now the reachability analyzer can determine that no matter which branch of the "if" is taken, the switch section endpoint is unreachable.
Is this good style?
No. Your original code was a lot more readable.
I've read switch statements are aweful in general - Is that true?
Opinions vary. Switch statements are very useful when there is a small number of very "crisp" alternatives whose behaviours do not interact in complex ways. Some people will tell you that switched logic should instead be handled by virtual methods or visitor patterns, but that can be abused as well.
Should I use a switch in this particular case?
I wouldn't.
How would you improve my code?
if ((Show == Display.All) ||
(expected.EXPENSE == true && Show == Display.Expense) ||
(expected.EXPENSE == false && Show == Display.NonExpense))
{
//Code
}
First off, don't name things IN ALL CAPS in C#.
Second, don't compare Booleans to true and false. They're already Booleans! If you want to know the truth of statement X you would not say in English "is it true that X is true?" You would say "Is X true?"
I would likely write:
if (Show == Display.All ||
Show == Display.Expense && expected.Expense ||
Show == Display.NonExpense && !expected.Expense)
{
//Code
}
Or, even better, I would abstract the test away into a method of its own:
if (canDisplayExpenses())
{
//Code
}
Or abstract the whole thing away:
DisplayExpenses();
The compiler will not understand what you mean here.
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
break;
// missing break here
case Display.NonExpense:
The compiler will not connect the dots and understand that the break; statement inside your if statement is linked to the switch statement. Instead it will try to link it to a loop, since break; statements on their own can only be used with loops, to break out of it.
That means that your case block is missing its break statement to complete it, and thus the compiler complains.
Instead of trying to wring the necessary code out of a switch statement, I would instead break up your original if statement.
This is yours:
if ((Show == Display.All) || (expected.EXPENSE == true && Show == Display.Expense) || (expected.EXPENSE == false && Show == Display.NonExpense))
{
//Code
}
This is how I would write it:
bool doDisplayExpected =
(Show == Display.All)
|| (Show == Display.Expense && expected.EXPENSE)
|| (Show == Display.NonExpense && !expected.EXPENSE);
if (doDisplayExpected)
{
// code
}
You don't have to pack everything on one line.
Also, I would try to name properties so that they're easier to read, I would rename the EXPENSE property to IsExpense so that the above code would read like this:
bool doDisplayExpected =
(Show == Display.All)
|| (Show == Display.Expense && expected.IsExpense)
|| (Show == Display.NonExpense && !expected.IsExpense);
if (doDisplayExpected)
{
// code
}
Then, ideally, I would refactor out the sub-expressions to methods:
bool doDisplayExpected =
ShowAll()
|| ShowExpense(expected)
|| ShowNonExpense(expected);
if (doDisplayExpected)
{
// code
}
public bool ShowAll()
{
return Show == Display.All;
}
public bool ShowExpense(Expected expected)
{
return Show == Display.Expense && expected.EXPENSE;
}
public bool ShowNonExpense(Expected expected)
{
return Show == Display.NonExpense && !expected.EXPENSE;
}
Then you can put the expression back into the if-statement:
if (ShowAll() || ShowExpense(expected) || ShowNonExpense(expected))
{
// code
}
This should be easier to read, and change later on.
Use if statements and extract complex conditions into methods, e.g
if (ShowAll() || ShowExpense())
{
}
Remember about OOP and polymorphism every time you write such 'switch', adding another
case to that code will be a nightmare
see this and similar (C++) instructions about converting switches
P.S if you are interested in making your code clean and readable, consider reading Smalltalk Best Practice Patterns by Kent Beck and/or Clean Code by Uncle Bob
I really enjoyed both of them, highly recommend.
If you want readability, just throw away your syntax trash:
if (Show == Display.All || expected.EXPENSE && Show == Display.Expense || !expected.EXPENSE && Show == Display.NonExpense)
{
//Code
}
Provide the else part for each of them so it will not throw error, however as others say, you actually don't need switch in this case.
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
// do what you want
break;
else
// do what you want
break;
case Display.NonExpense:
if (expected.EXPENSE == true)
// do what you want
break;
else
// do what you want
break;
case Display.All:
//Code
break;
}
The reason why you get this error is that you are not defining break statements.
You defined the break conditionally.
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
break;
// Note that the break above is in scope of you if statement, and will
// result in a compiler error
case Display.NonExpense:
...
}
Either make sure every case statement has its own break or group the case statements as follows.
switch (Show)
{
case Display.Expense:
case Display.All:
// do stuff
// Expense and All have the same behavior
}
Refactor out the if statements so you can express it like so:
if (isDisplayAll() || isExpense(expected) || isNonExpense(expected))
{
// Code
}
The extracted logic:
private bool isDisplayAll()
{
return (Show == Display.All);
}
private bool IsExpense(Expected expected)
{
return expected.EXPENSE && (Show == Display.Expense);
}
private bool IsNonExpense(Expected expected)
{
return !expected.EXPENSE && (Show == Display.NonExpense);
}
Agree with Dennis, you don't want a switch case for this problem.
Although probably less readable, you can also use shorter:
if (Show == Display.All || (expected.EXPENSE == (Show == Display.Expense)))
{
//Code
}