3

I was trying to store and retrieve additional information from enums. I ended up with 2 methods for it. The first method is by using custom attributes. https://stackoverflow.com/a/22054994/5078531 https://stackoverflow.com/a/35040378/5078531

public class DayAttribute : Attribute
{
    public string Name { get; private set; }

    public DayAttribute(string name)
    {
        this.Name = name;
    }
}

enum Days
{
    [Day("Saturday")]
    Sat,
    [Day("Sunday")]
    Sun
}

public static TAttribute GetAttribute<TAttribute>(this Enum value)
        where TAttribute : Attribute
    {
        var enumType = value.GetType();
        var name = Enum.GetName(enumType, value);
        return enumType.GetField(name).GetCustomAttributes(false).OfType<TAttribute>().SingleOrDefault();
    }

The second method I found here, by writing an extension method on enums. https://stackoverflow.com/a/680515/5078531

public enum ArrowDirection
{
    North,
    South,
    East,
    West
}

public static class ArrowDirectionExtensions
{
     public static UnitVector UnitVector(this ArrowDirection self)
     {         
         switch(self)
         {
             case ArrowDirection.North:
                 return new UnitVector(0, 1);
             case ArrowDirection.South:
                 return new UnitVector(0, -1);
             case ArrowDirection.East:
                 return new UnitVector(1, 0);
             case ArrowDirection.West:
                 return new UnitVector(-1, 0);
             default:
                 return null;
         }
     }
}

If am looking for the performance which method should I choose ? or is there any other efficient methods which am missing?

2
  • 3
    Both are actually bad. If you want a struct with predefined values, use a struct with predefined values, eg with static readonly fields that hold the predefined values. If you want to prevent people from creating their own instances, make the constructor private Commented Jul 5, 2016 at 10:25
  • 1
    "If am looking for the performance which method should I choose" : Neither. First you should define your performance needs (for production work, "as fast as possible" is rarely an acceptable definition), then you should pick the most readable method. Then you should benchmark. If this specific part of your code is a benchmark, you should either change it or, more likely, change the calling code to call into it less often. Commented Jul 6, 2016 at 13:01

2 Answers 2

3

Both are valid ways of implementing it; as are many other ways. Personally, I like the convenience of the first. The performance penalty of reflection can be mitigated by processing the attributes once only, and storing (presumably in a static field) - potentially as a flat array if the enum values are contiguous and 0-based; otherwise, perhaps in a dictionary.

Sign up to request clarification or add additional context in comments.

Comments

0

You can make DayaAttributeCache more generic if you like such that it can store other enum and attribute types. I just did this quick to show a caching approach. Enum values have to be continuous starting at 0 but this can be changed to handle that case if needed.

public static class DaysAttributeCache
{
    private static readonly string[] Cache;

    static DaysAttributeCache()
    {
        Type enumType = typeof(Days);
        Cache = new string[Enum.GetValues(enumType).Length];

        foreach (Enum value in Enum.GetValues(enumType))
        {
          var name = Days.GetName(enumType, value);

          DayAttribute attribute = enumType
              .GetField(name)
              .GetCustomAttributes(false)
              .OfType<DayAttribute>()
              .SingleOrDefault();

          string weekDay = attribute?.Name;
          Cache[((IConvertible)value).ToInt32(CultureInfo.InvariantCulture)] = weekDay;
        }
    }

    public static string GetWeekday(this Days value)
    {
        return Cache[(int)value];
    }
  }

Called like this...

string saturday = Days.Sat.GetWeekday();

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.