Click here to Skip to main content
Licence CPOL
First Posted 7 Apr 2009
Views 10,227
Bookmarked 10 times

Refactoring "switch cases".

By | 2 Jul 2009 | Technical Blog
Hello to everyone, I want to show you how to apply a simple refactoring trick to a common pattern, the "switch case" statement. Please take a look at the following program (a console app) : class Program     {         private static stri
A Technical Blog article. View original blog here.[^]

Hello to everyone, I want to show you how to apply a simple refactoring trick to a common pattern, the "switch case" statement.

Please take a look at the following program (a console app) :

class Program
    {
        private static string options = null;
        private static readonly Type sportsEnumType = typeof(SportNews.Sports);
        static void Main(string[] args)
        {
            SportNews news = new SportNews();
            while (true)
            {
                Console.WriteLine();
                DisplayOptions();
                string key = Console.ReadKey().KeyChar.ToString();
                Console.WriteLine();
                try
                {
                    SportNews.Sports sport = (SportNews.Sports)(Enum.Parse(
                        sportsEnumType, key));
                    news.DisplayNews(sport);
                }
                catch(Exception ex)
                {
                    Console.WriteLine(ex);
                    Console.ReadLine();
                    return;
                }
 
            }
        }
        private static void DisplayOptions()
        {

            if (options == null)
            {
                StringBuilder optionsBuilder = new StringBuilder();
                FieldInfo[] enumFields = sportsEnumType.UnderlyingSystemType.GetFields(
                    BindingFlags.Public | BindingFlags.Static);
                foreach (FieldInfo enumField in enumFields)
                {
                    object enumValue = enumField.GetRawConstantValue();
                    SportNews.Sports sport = (SportNews.Sports)(enumValue);
                    optionsBuilder.AppendFormat("To display the news for {0} press {1}\n",
                        sport, enumValue);
                }
                options = optionsBuilder.ToString();
            }
            Console.WriteLine(options);
        }
    }

    public class SportNews
    {
        public enum Sports
        {
            Soccer = 0,
            BasketBall = 1,
            Rugby = 2,
            VolleyBall = 3
        }
        public void DisplayNews(Sports sport)
        {
            switch (sport)
            {
                case Sports.Soccer:
                    DisplayNewsForSoccer();
                    break;
                case Sports.BasketBall:
                    DisplayNewsForBasketBall();
                    break;
                case Sports.Rugby:
                    DisplayNewsForRugby();
                    break;
                case Sports.VolleyBall:
                    DisplayNewsForVolleyBall();
                    break;
                default:
                    throw new NotImplementedException(string.Format(
                         "The method for the sport {0} is not implemented", sport));
            }
        }
 
        private void DisplayNewsForSoccer()
        {
            Console.WriteLine("Displaying News for Soccer");
            // Real implementation below
            // Do something
        }
        private void DisplayNewsForBasketBall()
        {
            Console.WriteLine("Displaying News for BasketBall");
            // Real implementation below
            // Do something
        }
 
        private void DisplayNewsForRugby()
        {
            Console.WriteLine("Displaying News for Rugby");
            // Real implementation below
            // Do something
        }
 
        private void DisplayNewsForVolleyBall()
        {
            Console.WriteLine("Displaying News for VolleyBall");
            // Real implementation below
            // Do something
        }
     }

What this does?, well, simply ask to the user to press a given key to execute a determined action.

The running program looks like this:

console_app_running

Very simple isn't?

This is fine for the number of alternatives that we are going to handle, but,what about if you add more items (+10) to the enum, you would need to add more cases to the switch statement, and so on. This is a very error prone process and also a maintenance nightmare.

What to do then? Well, the solution is very simple, you would need to change the switch statement by a lookup table, a Dictionary object is a good candidate to do this.

SHOW ME THE CODE!!. Here it is:

First lets create our Dictionary instance in the SportNews class constructor :

      private Dictionary<Sports, Action> lookupTable;
        public SportNews()
        {
            lookupTable = new Dictionary<Sports, Action>()
            {
                { Sports.Soccer, DisplayNewsForSoccer },
                { Sports.BasketBall, DisplayNewsForBasketBall },
                { Sports.Rugby, DisplayNewsForRugby },
                { Sports.VolleyBall, DisplayNewsForVolleyBall }
            };
        }

Now lets change the DiplayNews method to get ride of the switch statement, it will end up as:

        public void DisplayNews(Sports sport)
        {
            Action displayMethod;
            if (lookupTable.TryGetValue(sport, out displayMethod))
            {
                displayMethod.Invoke();
            }
            else
            {
                throw new NotImplementedException(string.Format(
                   "The method for the sport {0} is not implemented", sport));
            }
        }

Isn't this more simple and clean?

Obviously, this code could be refactored even more, but for the purpose of the article I think is fine.

The final working demo can be found here.

Bye bye.

Shameless plug: You can check this article on my blog here.  

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

emiaj

Web Developer

Peru Peru

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralMy vote of 2 PinmemberBigTuna4:30 9 Apr '09  
GeneralRe: My vote of 2 Pinmemberemiaj4:40 13 Apr '09  
From the article:
Obviously, this code could be refactored even more, but for the purpose of the article I think is fine.

 
I completely agree with you, the next step to refactor this code even better is the use of the Strategy Pattern.
 
Thanks for your feedback.
 

GeneralRe: My vote of 2 Pinmemberemiaj5:26 24 Jun '09  
Generalswitch() Pinmembertonyt20:56 8 Apr '09  
GeneralMy vote of 1 PinmembernextDev.net20:52 7 Apr '09  
GeneralRe: My vote of 1 PinmemberDoncp10:46 8 Apr '09  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web02 | 2.5.120604.1 | Last Updated 2 Jul 2009
Article Copyright 2009 by emiaj
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid