Before going into details about how you could refactor a switch statement first I should say that there's nothing wrong with this statement (as with any other C#, VB.NET or whatever statement). Most probably you would want to refactor a switch in one of these scenarios:
One possible way to refactor a switch statement is by using the Derick Bailey's approach and use the "Descriptive State Enumeration" approach. What Derick manages to do is turn this code:
into something like this:
OrderStatus InProcess =
OrderStatus Totaled =
OrderStatus Tendered =
InProcessStatus : OrderStatus
TotaledStatus : OrderStatus
TenderedStatus : OrderStatus
total = order.GetTotal();
order.Status = OrderStatus.Totaled;
In short what we do here (actually what Derick suggests) is to wrap each case into a new state and delegate some responsibility to each state rather than doing everything in the switch statement in strongly procedural code. This way when you need to introduce a new behavior you won't need to modify the existing code but rather create a new state.
If for some reason you don't want to delegate responsibility to each state and if it turns out that you'll need too many states you could consider using Chris Brandsma's approach and use a Dictionary. What Chris does is turning this code:
var dictionary =
Some of you may not like this kind of refactoring but nevertheless if it helps you have cleaner code at the end, why not?
In some cases you may have a sequence of several operations where each operation relies on the result or the completion of the previous operation. In such scenarios you could take advantage of what Joel Ross suggests, so assuming you have the following lines of code:
DoColorWork(ColorObject color, ColorManager manager)
using the Strategy pattern you could refactor them to:
ColorManager manager = GetColorManager(color);
ColorManager GetColorManager(ColorObject color)
Instead of the Strategy pattern you could try using the Visitor pattern which is also a good option when you feel tempted to implicitly switch by a type's name (example taken from here).
// Cast employee to Engineer and do something
// Cast employee to Salesman and do something
// Cast employee to Manager and do something
Well, the refactored code will result in much more lines of code but at least we'll be safe if we decide to rename some of the classes inheriting from the Employee class. Also we won't need to cast the employee instance to the different subclasses. And last but not least we'll have code which will have more and clearer points of extensibility:
Engineer : Employee
Salesman : Employee
Manager : Employee
EmployeeSortVisitor : IVisitor
What we should finally do is just instantiate a new EmployeeSortVisitor in the SortEmployee method and call the Accept method of the employee.
var employeeVisitor =
For those of you who find the switch statement syntax kind of limiting you could check Bart De Smet's functional switch approach.
You'll be able to do some pretty cool things, such as:
.Case(s => s.StartsWith(
), s =>
" starts with B."
" starts with Ba."
" starts with who knows what."
Hope this helps :)
Copyright © 2017, Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
Progress, Telerik, and certain product names used herein are trademarks or registered trademarks of Progress Software Corporation and/or one of its subsidiaries or affiliates in the U.S. and/or other countries. See Trademarks or appropriate markings.