A Less Ugly Switch Statement For C#


I know switch statements are considered “evil” because they are very procedural code, they violate the Open-Closed Principle, etc etc. But every now and then I don’t see a need to do anything more than a switch statement because the complexity of the scenario does not need anything more, and the code’s maintainability is not going to be so adversely affected by it.

I had such a case today, when examining the “Status” value – an enum – that is found on the data structure returned by a web service call. Here’s the original code:

   1: switch (newContainer.Status)

   2: {

   3:     case ScannedAssetState.ConfirmAssetRemove:

   4:         {

   5:             ConfirmAssetRemove(newContainer.TagInfo, assetTag);

   6:             break;

   7:         }

   8:     case ScannedAssetState.Error:

   9:         {

  10:             View.ShowError(newContainer.Errors.FirstOrDefault());

  11:             break;

  12:         }

  13:     case ScannedAssetState.Success:

  14:         {

  15:             RestartWithNewContainer(newContainer.TagInfo);

  16:             break;

  17:         }

  18:     default:

  19:         {

  20:             Init(newContainer.TagInfo);

  21:             break;

  22:         }

  23: }

</div> </div>

Though this code isn’t horrible, I do tend to hate the excessive syntax of switch statements. So… I wrote a simple fluent API to condense this code. Here’s the end result:

   1: Switch.On(newContainer.Status)

   2:     .Case(ScannedAssetState.ConfirmAssetRemove, () => ConfirmAssetRemove(newContainer.TagInfo, assetTag))

   3:     .Case(ScannedAssetState.Error, () => View.ShowError(newContainer.Errors.FirstOrDefault()))

   4:     .Case(ScannedAssetState.Success, () => RestartWithNewContainer(newContainer.TagInfo))

   5:     .Default(() => Init(newContainer.TagInfo));

</div> </div>

And here’s the simple way I implemented it:

   1: public static class Switch

   2: {

   3:     public static Switch<T> On<T>(T value)

   4:     {

   5:         return new Switch<T>(value);

   6:     }

   7: }

   8:  

   9: public class Switch<T>

  10: {

  11:     private bool hasBeenHandled;

  12:     private readonly T value;

  13:  

  14:     public Switch(T value)

  15:     {

  16:         this.value = value;

  17:     }

  18:  

  19:     public Switch<T> Case(T comparisonValue, Action action)

  20:     {

  21:         if (AreEqual(value, comparisonValue))

  22:         {

  23:             hasBeenHandled = true;

  24:             action();

  25:         }

  26:         return this;

  27:     }

  28:  

  29:     public void Default(Action action)

  30:     {

  31:         if (!hasBeenHandled)

  32:             action();

  33:     }

  34:  

  35:     private bool AreEqual(T actualValue, T comparisonValue)

  36:     {

  37:         return Equals(actualValue, comparisonValue);

  38:     }

  39: }

</div> </div>

I’m sure the AreEqual method could use some work to make it more robust, but it satisfied my current need just fine.

Of course, this code is nothing ground-breaking and I’m sure plenty of people will tell me how much worse it is than the original, and how I should have / could have avoided a switch statement in the first place… Meh… It was a fun little exercise. We’ll see how long it actually lives in my code base.

Technical Debt Is Like Your Friend, The Mafia Bookie