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.

 1public static class EnumExtensions
 2{
 3    private static Dictionary<Enum, string> enumStringValues = new Dictionary<Enum, string>();
 4    public static string ToStringCached(this Enum myEnum)
 5    {   
 6        string textValue;
 7        if (enumStringValues.TryGetValue(myEnum, out textValue))
 8        {
 9            return textValue;
10        }
11        else
12        {
13            textValue = myEnum.ToString();
14            enumStringValues[myEnum] = textValue;
15            return textValue;
16        }
17    }
18}

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

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

and

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

To try this out –

 1static void Main(string[] args)
 2{
 3    var marching =  Movement.March; 
 4     
 5    var monthOfMarch = Month.March;
 6    var monthOfApril = Month.April;
 7 
 8    Console.WriteLine(marching.ToStringCached()); // this will store it in the dictionary
 9    Console.WriteLine(marching.ToStringCached()); // this will retrieve it from the dictionary
10     
11    Console.WriteLine(monthOfMarch.ToStringCached()); // this will store it in the dictionary
12    Console.WriteLine(monthOfMarch.ToStringCached()); // this will retrieve it from the dictionary
13 
14    Console.WriteLine(monthOfApril.ToStringCached()); // this will store it in the dictionary
15    Console.WriteLine(monthOfApril.ToStringCached()); // this will retrieve it from the dictionary
16}

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.

comments powered by Disqus

Related