A quick note on case labels

When we use a language, often we tend to overlook some of the more obvious constructs or be frustrated by what we think should work.  For example, assume we have this simple problem – our function receives a value and based on that value we run through a switch, but we have code that will be run for multiple cases.  Explaining what I mean in words is tough – so let’s look at what I’m trying to say in code.  Assume we have these enums:


[Flags]
enum Foo
{
  NoFoo = 0,
  FooA = 1,
  FooB = 2,
  FooC = 4
}

enum Bar
{
  A,
  B,
  C
}


We want a function that will take in a Bar, and based on that create a Foo.  If Bar is A, the the resulting Foo is a combination of FooA, FooB and FooC.  If Bar is B, then it’s a combination of FooB and FooC.  If Bar is C, then the result is just FooC.  In C, we’d just do this:


Foo FooBar(Bar bar)
{
  Foo foo = Foo.NoFoo;

  switch (bar)
  {
    case Bar.A:
      foo |= Foo.FooA;
    case Bar.B:
      foo |= Foo.FooB;
    case Bar.C:
      foo |= Foo.FooC;
    break;
  }
  return foo;
}


Letting each case fall into the next intentionally. Yes it’s a contrived example, but you get the idea.  There are cases when we need to do processing like this (like a project I’m doing right now).


Well C# doesn’t like this type of construct – I’m not certain why it’s illegal (other than missing breaks are common bugs) – but the compiler will say ‘Error: Control cannot fall through from one case label (‘case 0:’) to another‘.  So you might code a ‘fix’ like this:


Foo FooBar(Bar bar)
{
   Foo foo = Foo.NoFoo;

   switch (bar)
   {
      case Bar.A:
         foo |= Foo.FooA;
      break;
      case Bar.B:
         foo |= Foo.FooA;
         foo |= Foo.FooB;
      break;
      case Bar.C:
         foo |= Foo.FooA;
         foo |= Foo.FooB;
         foo |= Foo.FooC;
      break;
   }
   return foo;
}


Not too bad, but if you have to do more processing than a single line it gets ugly and maintainability goes downhill fast.


The thing to keep in mind in C# is that those case statements are actually labels, so you can use them as such, meaning they are valid goto targets, so this code is perfectly valid:


Foo FooBar3(Bar bar)
{
   Foo foo = Foo.NoFoo;

   switch (bar)
   {
      case Bar.A:
         foo |= Foo.FooA;
         goto case Bar.B;
      case Bar.B:
         foo |= Foo.FooB;
         goto case Bar.C;
      case Bar.C:
         foo |= Foo.FooC;
      break;
   }
   return foo;
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s