Introduction
A number of online discussions can be found regarding the drawbacks of switch expressions or the recommendation to avoid using them altogether.
Several of us have likely received feedback on our pull requests urging us to eliminate switch expressions.
Here are some interesting discussions and blogs to check out:
Switch statements are bad?
Eliminating switch
statements
Code Smells, Switch Statement
The purpose of this article is not to emphasize the pros and cons of using switch expressions.
Instead, let's explore how we can restructure our code to eliminate switch expressions if necessary.
Code Setup
We begin by creating a basic console application that associates habits with pets.
Let's add a class named Habit:
public class Habit
{
public bool PlayFool { get; set; } = true;
public bool Shy { get; set; } = true;
public bool LoveColdShowers { get; set; } = true;
public bool Lazy { get; set; } = false;
public bool Bite { get; set; } = true;
public bool Valid { get; set; } = true;
}
It consists of simple boolean properties like Shy
and Lazy
.
The next step is to add the enum Pet
:
public enum Pet
{
None,
Cat = 1,
Dog = 2,
Rabbit = 3
}
Moving forward, let's introduce a class called PetsHabit
which contains public methods for retrieving the pet's habits:
public class PetsHabit
{
public Habit MapHabitsUsingSwitch(Pet pet)
{
return pet switch
{
Pet.Dog => new Habit
{
LoveColdShowers = false,
Shy = false
},
Pet.Cat => new Habit
{
LoveColdShowers = false,
Lazy = true,
Shy = false,
},
Pet.Rabbit => new Habit
{
PlayFool = false,
Lazy = true,
},
_ => new Habit { Valid = false }
};
}
}
PetsHabit
includes the method MapHabitsUsingSwitch
which takes a single parameter of type Pet.
MapHabitsUsingSwitch
returns the pet's habit and relies on a switch expression to generate a new habit.
Next, let's investigate alternative approaches to refactoring from switch expressions while maintaining the same logic.
Refactoring Switch Expression with If
Although we can refactor the switch expression into if statements, it's not the best choice.
Nevertheless, for the sake of exploration, let's consider how we can transition from switch expressions to if statements.
Now, let's add another method called MapHabitsUsingIf
in the PetsHabit
:
public Habit MapHabitsUsingIf(Pet pet)
{
if (pet is Pet.Dog)
{
return new Habit
{
LoveColdShowers = false,
Shy = false
};
}
if (pet is Pet.Cat)
{
return new Habit
{
LoveColdShowers = false,
Lazy = true,
Shy = false,
};
}
if (pet is Pet.Rabbit)
{
return new Habit
{
PlayFool = false,
Lazy = true,
};
}
return new Habit { Valid = false };
}
Instead of utilizing a switch expression, MapHabitsUsingIf
employs if statements to determine the pet's habit.
Certainly, if we need to refactor from switch expressions, substituting them with if statements is not the optimal solution.
This approach may introduce similar or even more drawbacks.
We must find a better approach - let's examine that in the following section.
Switch Expression Refactoring with Delegate
There are various ways to refactor switch expressions, but the most common suggestion we encounter online is to utilize a strategy pattern.
public class PetsHabit
{
public Habit MapHabitsUsingDelegate(Pet pet)
{
var habitsToFunctionMapper = GetHabitFunction(pet);
if ( habitsToFunctionMapper.TryGetValue (
pet,
out var getHabitFunbction)
)
{
return getHabitFunbction();
}
return new Habit { Valid = false };
}
private Dictionary<Pet, Func<Habit>> GetHabitFunction(Pet pet)
{
return new Dictionary<Pet, Func<Habit>>
{
{ Pet.Cat, this.GetCatHabit },
{ Pet.Dog, this.GetDogHabit },
{ Pet.Rabbit, this.GetRabbitHabbit },
};
}
}
private Habit GetCatHabit()
{
return new Habit
{
LoveColdShowers = false,
Lazy = true,
Shy = false,
};
}
private Habit GetDogHabit()
{
return new Habit
{
LoveColdShowers = false,
Shy = false
};
}
private Habit GetRabbitHabbit()
{
return new Habit
{
PlayFool = false,
Lazy = true,
};
}
Top comments (2)
Probably too complex for no benefit. Now you need to decode that "Habit" when reading it instead of seeing it plain in the switch state.
Maybe if you need a million habits, but this is honestly not good.
Great knowledge in dotNet and CSharp.
Let's get connected..