How will you make it if you never even try?

April 1, 2009

C# Delights: You can put Extension Methods onto Enums!

Filed under: C# — Tags: , , , , — charlieflowers @ 8:04 am

Often, you need to associate other information with the members of an Enum. For example, say you have the following enum:

public enum DaysOfWeek : int
{
   Sunday = 1,
   Monday = 2,
   Tuesday = 3,
   Wednesday = 4,
   Thursday = 5,
   Friday = 6,
   Saturday = 7
}

That’s all well and good. But say you need to associate additional information with each enum member. For example, say your legacy database represents the days of the week with the following 2 letter codes: “Sn”, “Mo”, “Te”, “Wn”, “Tr”, “Fi”, “St”. Notice I picked codes that are not intuitive and are not always the first 2 characters. Crazy, but we all know legacy databases can be crazy.

Also, let’s imagine that your company needs to associate a decimal hourly rate with each day, representing the fact that you charge different rates for different days.

C# has a very nice, new way you can do this. Before C# 3.0, the best way I knew of to handle this was to not use an Enum at all. Rather, I would make a class that was much like a singleton, but with more than one instance. It would have a private constructor, so that no other classes outside of it could make instances of it. However, it would expose static properties with the exact set of instances that were allowed (7 in our case, and the properties would be named “Sunday”, “Monday”, etc.). Each instance would have properties for “DatabaseCode”, “Name” and “HourlyRate”. That’s not bad, but the new way is better in many cases.

The new way is this: You can place extension methods onto Enums! So, in our case, we would do the following:

public static class DaysOfWeekExtensions
{
   private static string[] databaseCodes = new string[] { "Sn", "Mo", "Te",
      "Wn", "Tr", "Fi", "St" };

   private static decimal[] rates = new decimal[] { 2.5m, 3.6m, 0m, 1.2m,
      8.8m, 42m, 3.6m };

   public static string DatabaseCode(this DaysOfWeek self)
   {
      int index = (int)self - 1;
      return databaseCodes[index];
   }

   public static decimal HourlyRate(this DaysOfWeek self)
   {
       int index = (int)self - 1;
       return rates[index];
   }
}

And then you’d use it like this:

Console.WriteLine("For Tuesday, the database code is " + 
   DaysOfWeek.Tuesday.DatabaseCode() + " and we charge " +
   DaysOfWeek.Tuesday.HourlyRate() + ".");

Click here for another example.

Create a free website or blog at WordPress.com.