Switch Enum - Refactoring — Digitteck
Switch Enum - Refactoring
dotnet·7 March 2018·2 min read

Switch Enum - Refactoring

Description

A switch statement internally behaves like a set of conditioned jumps. It's an expression and the nature of it doesn't take advantage of OOP concepts. The readability and complexity of switch statements are unarguably on the low side and need improvements. Consider the following example:

csharp
enum Status
    {
        Active = 1,
        Inactive = 2,
        AccessGranted = 4,
        AccessNotAllowed = 8
    }

This enum defines a set of flags that may describe the access of a certain individual to a set of data. For this example let's assume that a user can access data only if it's Active and has Access. Then on the client side you would have to deal with states like this:

csharp
Status guyStatus = Status.AccessGranted | Status.Active;
            switch (guyStatus)
            {
                case Status.AccessGranted | Status.Active:
                    Console.WriteLine("Guy is active and access is granted - Allowed");
                    Console.WriteLine("Some operations on status active and allowed");
                    break;
                case Status.AccessGranted | Status.Inactive:
                    Console.WriteLine("Guy is inactive and access is granted - NotAllowed");
                    break;
                case Status.AccessNotAllowed | Status.Active:
                    Console.WriteLine("Guy is active and access is not granted - NotAllowed");
                    break;
                case Status.AccessNotAllowed | Status.Inactive:
                    Console.WriteLine("Guy is inactive and access is not granted - NotAllowed");
                    break;
                default:
                    Console.WriteLine("Not Allowed");
                    break;
            }

Problem

It's obvious that the more flags you define, the more the complexity increases and also the readability decreases.

Solution

Strategy Pattern is used to refactor this example, to turn the instructions into objects, but this is adapted for switch statements.

Classical Strategy Pattern implies defining a base class / interface upon which child strategies inherit. For this kind of problem we do not define more classes, but a dictionary of strategies.

We define a class that incorporates the functionality of the access. In the end, it's the object's responsibility of choosing a strategy based on the status:

csharp
class GuyStatus
    {
        //Status is private - who should care of this representation? It's a matter of this object
        [Flags]
        private enum StatusRepresentation
        {
            Active = 1,
            Inactive = 2,
            AccessGranted = 4,
            AccessNotAllowed = 8
        }

        private StatusRepresentation status;

        protected Dictionary<int, Action> strategies = new Dictionary<int, Action>();

        public GuyStatus()
        {
            strategies.Add((int)(StatusRepresentation.Active | StatusRepresentation.AccessGranted),
                        () => { Console.WriteLine("Guy is active and access is granted - Allowed"); });

            strategies.Add((int)(StatusRepresentation.Active | StatusRepresentation.AccessNotAllowed),
                        () => { Console.WriteLine("Guy is active and access is not granted - NotAllowed"); });

            strategies.Add((int)(StatusRepresentation.Inactive | StatusRepresentation.AccessGranted),
                        () => { Console.WriteLine("Guy is inactive and access is granted - NotAllowed"); });

            strategies.Add((int)(StatusRepresentation.Inactive | StatusRepresentation.AccessNotAllowed),
                        () => { Console.WriteLine("Guy is inactive and access is not granted - NotAllowed"); });
        }

        public static GuyStatus ActiveAllowed()
        => new GuyStatus { status = StatusRepresentation.Active | StatusRepresentation.AccessGranted };

        public static GuyStatus ActiveNotAllowed()
      => new GuyStatus { status = StatusRepresentation.Active | StatusRepresentation.AccessNotAllowed };

        public virtual void Execute(Action action)
        {
            if (status == (StatusRepresentation.AccessGranted | StatusRepresentation.Active)
                && this.strategies.Keys.Any(x => x == (int)this.status))
            {
                this.strategies[(int)this.status].Invoke();
                action();
            }
            else
                Console.WriteLine("Not Allowed");
        }
    }

And the client usage:

csharp
GuyStatus guyStat = GuyStatus.ActiveAllowed();

            guyStat.Execute(() =>
            {
                Console.WriteLine("Some operations on status active and allowed");
            });

Tags

.NETC#Practices
digitteck

© 2026 Digitteck