Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If Condition inside switch case [duplicate]

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
}
like image 809
AngelicCore Avatar asked Apr 01 '13 11:04

AngelicCore


5 Answers

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();
like image 127
Eric Lippert Avatar answered Nov 02 '22 19:11

Eric Lippert


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.

like image 38
Lasse V. Karlsen Avatar answered Nov 02 '22 19:11

Lasse V. Karlsen


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.

like image 33
illegal-immigrant Avatar answered Nov 02 '22 20:11

illegal-immigrant


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
}
like image 33
Dennis Avatar answered Nov 02 '22 20:11

Dennis


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;
}
like image 2
Hossein Narimani Rad Avatar answered Nov 02 '22 19:11

Hossein Narimani Rad