Click here to Skip to main content
15,886,770 members
Articles / Programming Languages / C#

Refactoring "switch cases"

Rate me:
Please Sign up or sign in to vote.
2.80/5 (5 votes)
2 Jul 2009CPOL1 min read 20.1K   9   6
How to refactor "switch cases"

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):

C#
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 does this do? Well, simply ask 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 let's create our Dictionary instance in the SportNews class constructor:

C#
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 let's change the DisplayNews method to get rid of the switch statement, it will end up as:

C#
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 it is fine.

The final working demo can be found here.

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)


Written By
Web Developer
Peru Peru
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 2 Pin
BigTuna9-Apr-09 4:30
BigTuna9-Apr-09 4:30 
GeneralRe: My vote of 2 Pin
emiaj13-Apr-09 4:40
emiaj13-Apr-09 4:40 
GeneralRe: My vote of 2 Pin
emiaj24-Jun-09 5:26
emiaj24-Jun-09 5:26 
Generalswitch() Pin
tonyt8-Apr-09 20:56
tonyt8-Apr-09 20:56 
GeneralMy vote of 1 Pin
r.wcs7-Apr-09 20:52
r.wcs7-Apr-09 20:52 
GeneralRe: My vote of 1 Pin
Doncp8-Apr-09 10:46
Doncp8-Apr-09 10:46 

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

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