Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Action dictionaries instead of switch statements

I'm just reviewing some of my old code (have some spare time), and I noticed a rather lengthy switch statement. Due to gaining new knowledge, I have since refactored it in the following form:

private Dictionary<string, Action> createView
    {
        get
        {
            return new Dictionary<string, Action>()
            {
                {"Standard", CreateStudySummaryView},
                {"By Group", CreateStudySummaryByGroupView},
                {"By Group/Time", CreateViewGroupByHour}
            };
        }
    }

Would you consider this good practise, or is this simply a case of being superflous and unneccessary? I'm keen to ensure new techniques that I learn, are not being clever just for the sake of it, and that they actually add benefit to the code.

Thanks.

like image 937
Darren Young Avatar asked Aug 24 '11 10:08

Darren Young


People also ask

Could a dictionary be used instead of a switch statement?

Using if else is a old programming method, we can replace a long if else with switch statements. If we have so many if else satements or switch statements it is not good coding. We can use a dictionary for solving this problem.

Should switch statements be avoided?

Nested switch structures are difficult to understand because you can easily confuse the cases of an inner switch as belonging to an outer statement. Therefore nested switch statements should be avoided.

Are switch statements good practice?

Even though using if-else statements to accomplish this logic results in a functional code, it is best practice to use a switch statement if you have multiple if-else. It makes your code more concise and clearer to understand.

Does C# have switch statements?

C# Switch StatementsUse the switch statement to select one of many code blocks to be executed.


4 Answers

Long switch statements are a classic bad smell, and are always a target for refactoring.

The "standard" step to perform here is Replace Conditional with Polymorphism. This was one of the steps listed in Martin Fowler's book Refactoring (published 11 years ago in 1999).

Now that it's so easy to treat functions like objects (eg with Action) this might be just as good a solution.

And no, I don't think you're being clever for the sake of it. If I wanted to add another option in the future, I can easily see what needs to be done.

like image 74
Andrew Shepherd Avatar answered Nov 27 '22 22:11

Andrew Shepherd


Depending on your app you can avoid to always construct a new dictionary object, but declare it like a class member, initialize on first access and always return the same instance. But it's hard to say, if it will actually fit your needs. Like this I mean

public class MyClass 
{
   Dictionary<string, Action> dict = null; 

    private Dictionary<string, Action> createView
    {
        get
        {
            if(dict  == null) 
            {
              dict  = new Dictionary<string, Action>()
              {
                {"Standard", CreateStudySummaryView},
                {"By Group", CreateStudySummaryByGroupView},
                {"By Group/Time", CreateViewGroupByHour}
              };
            }

            return dict;
        }
    }

}

EDIT

From conceptual point of view, me replacing long swicth/case with dictionary TryGetValue is a pretty good solution.

Hope this helps...

like image 34
Tigran Avatar answered Nov 27 '22 21:11

Tigran


This approach is excellent.

I use it with more than just Action. It's also quite effective for filters and selectors. Something like:

var filters = new Dictionary<string, Func<MyEntity, bool>>()
{
    // ...
};

var query = entities.Where(filters["X"]);
like image 44
Enigmativity Avatar answered Nov 27 '22 21:11

Enigmativity


If the code, once written, is largely static and not subject to too much change then I'd have stuck with a switch. Your dictionary approach here, on the surface at least, lends itself nicely to being more dynamic - that is more requirements based though.

As for replacing switches everywhere with code using this approach, I'd personally not do that in most cases. My honest opinion is that would just be being clever for the sake of it, but it is still easily maintainable. Personal taste over best practise is the largest factor here, as I see it.

On the other hand, as others have said, this could be a workable solution to long switch statements. Then again something like the Strategy Pattern would also be a good way to support changes in behaviour.

like image 24
Adam Houldsworth Avatar answered Nov 27 '22 23:11

Adam Houldsworth