Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should one try to eliminate a switch statement? [duplicate]

I've come across a switch statement in the codebase I'm working on and I'm trying to figure out how to replace it with something better since switch statements are considered a code smell. However, having read through several posts on stackoverflow about replacing switch statements I can't seem to think of an effective way to replace this particular switch statement.

Its left me wondering if this particular switch statement is ok and if there are particular circumstances where switch statements are considered appropriate.

In my case the code (slightly obfuscated naturally) that I'm struggling with is like this:

private MyType DoSomething(IDataRecord reader)
{
    var p = new MyType
                {
                   Id = (int)reader[idIndex],
                   Name = (string)reader[nameIndex]
                }

    switch ((string) reader[discountTypeIndex])
    {
        case "A":
            p.DiscountType = DiscountType.Discountable;
            break;
        case "B":
            p.DiscountType = DiscountType.Loss;
            break;
        case "O":
            p.DiscountType = DiscountType.Other;
            break;
    }

    return p;
}

Can anyone suggest a way to eliminate this switch? Or is this an appropriate use of a switch? And if it is, are there other appropriate uses for switch statements? I'd really like to know where they are appropriate so I don't waste too much time trying to eliminate every switch statement I come across just because they are considered a smell in some circumstances.

Update: At the suggestion of Michael I did a bit of searching for duplication of this logic and discovered that someone had created logic in another class that effectively made the whole switch statement redundant. So in the context of this particular bit of code the switch statement was unnecessary. However, my question is more about the appropriateness of switch statements in code and whether we should always try to replace them whenever they are found so in this case I'm inclined to accept the answer that this switch statement is appropriate.

like image 995
mezoid Avatar asked Jul 01 '09 23:07

mezoid


People also ask

Can you have duplicate cases in switch?

If two cases in a 'switch' statement are identical, the second case will never be executed. This most likely indicates a copy-paste error where the first case was copied and then not properly adjusted.

How do you stop a switch statement?

You can use the break statement to end processing of a particular labeled statement within the switch statement. It branches to the end of the switch statement. Without break , the program continues to the next labeled statement, executing the statements until a break or the end of the statement is reached.

Should you avoid switch statements?

Therefore nested switch statements should be avoided. Specifically, you should structure your code to avoid the need for nested switch statements, but if you cannot, then consider moving the inner switch to another function.

Can you have duplicate cases in a switch C#?

In C#, duplicate case values are not allowed. The data type of the variable in the switch and value of a case must be of the same type. The value of a case must be a constant or a literal. Variables are not allowed.


3 Answers

This is an appropriate use for a switch statment, as it makes the choices readable, and easy to add or subtract one.

See this link.

like image 138
Lance Roberts Avatar answered Sep 25 '22 15:09

Lance Roberts


Switch statements (especially long ones) are considered bad, not because they are switch statements, but because their presence suggests a need to refactor.

The problem with switch statements is they create a bifurcation in your code (just like an if statement does). Each branch must be tested individually, and each branch within each branch and... well, you get the idea.

That said, the following article has some good practices on using switch statements:

http://elegantcode.com/2009/01/10/refactoring-a-switch-statement/

In the case of your code, the article in the above link suggests that, if you're performing this type of conversion from one enumeration to another, you should put your switch in its own method, and use return statements instead of the break statements. I've done this before, and the code looks much cleaner:

private DiscountType GetDiscountType(string discount)
{
    switch (discount)
    {
        case "A": return DiscountType.Discountable;
        case "B": return DiscountType.Loss;
        case "O": return DiscountType.Other;
    }
}
like image 40
Robert Harvey Avatar answered Sep 24 '22 15:09

Robert Harvey


I think changing code for the sake of changing code is not best use of ones time. Changing code to make it [ more readable, faster, more efficient, etc, etc] makes sense. Don't change it merely because someone says you're doing something 'smelly'.

-Rick

like image 44
Rick Avatar answered Sep 22 '22 15:09

Rick