Enum ToString(), Caching for Performance

Full source code available here.

A while ago I was working on a program that had to convert enums values to strings as it saved data.

When I removed the enum value from the data that was saved it went noticeably faster. Did a little digging and it seems that ToString() on the enum was using reflection every time it was called, even if it was same enum and member that was being saved.

Here is an extension method that stores the string value of the enum so it gets called only once and the rest of the time you are looking up a dictionary to read the string value from.

public static class EnumExtensions
{
    private static Dictionary<Enum, string> enumStringValues = new Dictionary<Enum, string>();
    public static string ToStringCached(this Enum myEnum)
    {   
        string textValue;
        if (enumStringValues.TryGetValue(myEnum, out textValue))
        {
            return textValue;
        }
        else
        {
            textValue = myEnum.ToString();
            enumStringValues[myEnum] = textValue;
            return textValue;
        }
    }
}

This works fine even if you two enums that share a member names, for example –

public enum Movement
{
    Walk = 1,
    March = 2,
    Run = 3,
    Crawl = 4,
}

and

public enum Month
{
    January = 1,
    February = 2,
    March = 3,
    April = 4,
    //snip...
}

To try this out –

static void Main(string[] args)
{
    var marching =  Movement.March; 
    
    var monthOfMarch = Month.March;
    var monthOfApril = Month.April;

    Console.WriteLine(marching.ToStringCached()); // this will store it in the dictionary
    Console.WriteLine(marching.ToStringCached()); // this will retrieve it from the dictionary
    
    Console.WriteLine(monthOfMarch.ToStringCached()); // this will store it in the dictionary
    Console.WriteLine(monthOfMarch.ToStringCached()); // this will retrieve it from the dictionary

    Console.WriteLine(monthOfApril.ToStringCached()); // this will store it in the dictionary
    Console.WriteLine(monthOfApril.ToStringCached()); // this will retrieve it from the dictionary
}

Inside the dictionary you end up with three entries.

[0] [KeyValuePair]:{[March, March]}
Key [Enum {Movement}]:March
Value [string]:"March"

[1] [KeyValuePair]:{[March, March]}
Key [Enum {Month}]:March
Value [string]:"March"

[2] [KeyValuePair]:{[April, April]}
Key [Enum {Month}]:April
Value [string]:"April"

Full source code available here.

Leave a Reply

Your email address will not be published. Required fields are marked *