Mapping with Dictionary instead Switch

Recently I read the book “Refactoring: Improving the Design of Existing Code (2nd Edition)” by Martin Fowler (here…). A great book I highly recommend. Besides a lot of other useful informations and tips I started adapting to not use switch
statements for mapping-logic.
Why not using Switch?
The point is that a switch
statement can do a lot more things then just mapping value. From my own experience I can confirm that regularly a switch’s case
branch does more then one thing. More then just map value A to B. This leads in side-effects of the mapping logic. Further more the code does not clearly show its intent anymore, is harder to read, refactor and extend.
So we look for a better solution for mapping values. A solution that does only map values from A to B and no other logic can be placed into. It should show clearly that it only does a simple value-mapping.
That’s where dictionaries come into the play.
Dictionaries
Dictionary is a collection data-stucture that host key-value items. One can access values very fast by its indexer; the key. They have an optimized and short syntax to do exactly this. If you don’t use delegates as the value you can not add logic. Its a simple value translation table. So the intent should be very clear.
Example
Let’s map an enum value to a string (can be anything else). Here is the enum:
public enum Gender { Female, Male, Other }
Map value using a switch statement:
string MapGenderToString(Gender gender) { swtich (gender) { case Gender.Female: return "Woman"; case Gender.Male: return "Man"; case Gender.Other: return "Other"; default: throw new ArggumentRangeException(); } }
The problem here is that you can easily add any kind of logic (code) within one or more case
blocks. This would be a code-smell as written before.
Map value using a dictionary:
string MapGenderToString(Gender gender) { var mapping = new Dictionary<Gender, string> { { Gender.Female, "Woman" }, { Gender.Male, "Man" }, { Gender.Other, "Other" } } return mapping[gender]; }
It’s way harder – but not impossible – to missuse this mapping code.
Bonus value: Because the mapping is so simple one whould not even need an extra method for this. The mapping could be defined as a readonly-field and used directly in the parent code.
class PersonMapper { private readonly genderMapping = new Dictionary<Gender, string> { { Gender.Female, "Woman" }, { Gender.Male, "Man" }, { Gender.Other, "Other" } } public PersonDto MapPerson(Person person) => new PersonDto { ... Gender: genderMapping[person.Gender], ... } }
Hope this gives some inspiration. Let me know what you think about this.
Categories
nice blog post! i think its a good alternative to the switch statement!
LikeLike
Great idea – immediately could use it.
Using a DI like autofac, we manage to have a factory based on keyed registrations.
LikeLike
“the code does not clearly show its intent anymore, is harder to read, refactor and extend.”
What about the “switch operator”, though?
LikeLike