209

Which is the preferred way to convert an Enum to a String in .NET 3.5?

  • Enum.GetName
  • Enum.Format
  • ToString

Why should I prefer one of these over the others? Does one perform better?

user2864740
  • 60,010
  • 15
  • 145
  • 220
Eric Weilnau
  • 5,370
  • 4
  • 30
  • 30
  • 13
    I searched and was unable to find a duplicate. If you can provide a link I will delete this question. – Eric Weilnau Jan 27 '09 at 15:21
  • 1
    sometimes, using a switch statement is not the best practice (when you have big enumerations) you can use Dict<> instead – Guy L Oct 01 '11 at 08:24
  • 1
    If you want better performance you can use the class described in this article http://www.codeproject.com/KB/dotnet/enum.aspx. Usage will look like this Enum.ToString(yourValue) or Enum.ToString((int)yourValue) – ideafixxxer Nov 06 '11 at 17:27
  • 5
    Coding to not break dotfuscation is the epitome of the tail wagging the dog. SW producers are not thinking, "Let's make a great app so dotfuscator has something to do." Dofuscator exists to help facilitate SW development. If it can't do that ... can it! – micahhoover Jul 15 '14 at 18:14

15 Answers15

192

As of C#6 the best way to get the name of an enum is the new nameof operator:

nameof(MyEnum.EnumValue);

// Ouputs
> "EnumValue"

This works at compile time, with the enum being replaced by the string in the compiled result, which in turn means this is the fastest way possible.

Any use of enum names does interfere with code obfuscation, if you consider obfuscation of enum names to be worthwhile or important - that's probably a whole other question.

Keith
  • 150,284
  • 78
  • 298
  • 434
  • 15
    This deserves more attention. The obvious limitation notwithstanding, i.e. the requirement for compile-time input. In my opinion this should be preferred *whenever possible*. 'Rename' and 'find all references' take it into account as well, potentially avoiding magic strings and duplicate constants. – Timo Jan 13 '16 at 10:06
  • 2
    So I guess It won't work when the enum value is defined at runtime? Ex: MyEnum variableEnum; variableEnum = setEnumValueMethod(); nameof(variableEnum); – Maxter Feb 14 '19 at 17:43
  • 2
    @Maxter no, as `nameof(variableEnum)` will be `"variableEnum"`. It reflects (at build time) the _name_ of the field/property/param/variable not the _value_. – Keith Feb 15 '19 at 18:47
  • ye. unfortunately does not work if you do this: var someEnumvalue = SomeEnum.FooBar; nameof(someEnumvalue ); – Squibly Nov 11 '19 at 05:41
  • 1
    @Squibly yes, that will return `"someEnumValue"`, while you would need `nameof(SomeEnum.FooBar)` to get `"FooBar"`. – Keith Nov 11 '19 at 21:58
  • 1
    Much better than the one I used to use: `Enum.GetName(typeof(EnumType),instanceOfEnum)` bleugh – Peter Jun 12 '20 at 10:02
102

Works for our project...

public static String convertToString(this Enum eff)
{
    return Enum.GetName(eff.GetType(), eff);
}

public static EnumType converToEnum<EnumType>(this String enumValue)  
{
    return (EnumType) Enum.Parse(typeof(EnumType), enumValue);
}
Code Maverick
  • 20,171
  • 12
  • 62
  • 114
Sumtraveller
  • 1,186
  • 2
  • 9
  • 13
  • 8
    Enum.GetName takes the value as an object argument. This means that the value will be boxed and this will waste CPU resources on the allocation and on the garbage collection. If this is done a lot of time, Enum.GetName will have a much lower throughput than caching the values in a dictionary and looking for the name there. – Ran May 24 '14 at 05:28
  • @Ran so what is the solution , which to use instead? – Shaiju T Dec 18 '17 at 12:32
  • makes my project slower. toString() is faster. – d2k2 Jun 15 '20 at 20:16
38

Enum.GetName(...)

This is the most elegant method that is meant for it.

var enumValueString = Enum.GetName(typeof (MyEnum), MyEnum.MyValue);

Although I don't see any issues with calling .ToString() as it is simply shorter.

var enumValueString = MyEnum.MyValue.ToString();

With new C# 6 syntax you can use:

nameof(MyEnum.MyValue)
Andrei
  • 42,814
  • 35
  • 154
  • 218
37

In my tests, Enum.GetName was faster and by decent margin. Internally ToString calls Enum.GetName. From source for .NET 4.0, the essentials:

public override String ToString()
{
     return Enum.InternalFormat((RuntimeType)GetType(), GetValue());
}

private static String InternalFormat(RuntimeType eT, Object value)
{
    if (!eT.IsDefined(typeof(System.FlagsAttribute), false))
    {
        String retval = GetName(eT, value); //<== the one
        if (retval == null)
            return value.ToString();
        else
            return retval;
    }
    else
    {
        return InternalFlagsFormat(eT, value);
    }
}

I cant say that is the reason for sure, but tests state one is faster than the other. Both the calls involve boxing (in fact they are reflection calls, you're essentially retrieving field names) and can be slow for your liking.

Test setup: enum with 8 values, no. of iterations = 1000000

Result: Enum.GetName => 700 ms, ToString => 2000 ms

If speed isn't noticeable, I wouldn't care and use ToString since it offers a much cleaner call. Contrast

Enum.GetName(typeof(Bla), value)

with

value.ToString()
Community
  • 1
  • 1
nawfal
  • 70,104
  • 56
  • 326
  • 368
24

All of these internally end up calling a method called InternalGetValueAsString. The difference between ToString and GetName would be that GetName has to verify a few things first:

  1. The type you entered isn't null.
  2. The type you entered is, in fact an enumeration.
  3. The value you passed in isn't null.
  4. The value you passed in is of a type that an enumeration can actually use as it's underlying type, or of the type of the enumeration itself. It uses GetType on the value to check this.

.ToString doesn't have to worry about any of these above issues, because it is called on an instance of the class itself, and not on a passed in version, therefore, due to the fact that the .ToString method doesn't have the same verification issues as the static methods, I would conclude that .ToString is the fastest way to get the value as a string.

Noctis
  • 11,507
  • 3
  • 43
  • 82
David Morton
  • 16,338
  • 3
  • 63
  • 73
  • 4
    where did you check up these? What was the assembly version? I get very different results. – nawfal Jun 11 '13 at 00:00
18

Best I can find is this unrelated question on MSDN, which contains an XML snippet that answers this question. Any of these methods share the same flaw: they call enum.toString(), which does not work properly when using Dotfuscation. Other concerns appear to relate to indirect boxing (GetName and Format). Unfortunately, I can't find any performance reasons for using any of the above.

Paraphrasing from the xml snippet,

Passing a boxed enum to string.Format() or any other function can result in enum.ToString() being called. This will cause problems when Dotfuscating. You should not use enum.ToString(), enum.GetNames(), enum.GetName(), enum.Format() or enum.Parse() to convert an enum to a string. Instead, use a switch statement, and also internationalize the names if necessary.

jpaugh
  • 6,634
  • 4
  • 38
  • 90
17

Enum.GetName()

Format() is really just a wrapper around GetName() with some formatting functionality (or InternalGetValueAsString() to be exact). ToString() is pretty much the same as Format(). I think GetName() is best option since it's totally obvious what it does for anyone who reads the source.

shA.t
  • 16,580
  • 5
  • 54
  • 111
Tamas Czinege
  • 118,853
  • 40
  • 150
  • 176
9

I create a "Description" extension method and attach it to the enum so that i can get truly user-friendly naming that includes spaces and casing. I have never liked using the enum value itself as displayable text because it is something we developers use to create more readable code. It is not intended for UI display purposes. I want to be able to change the UI without going through and changing enums all over.

DancesWithBamboo
  • 4,176
  • 1
  • 19
  • 20
6

I don't know what the "preferred" method is (ask 100 people and get 100 different opinions) but do what's simplest and what works. GetName works but requires a lot more keystrokes. ToString() seems to do the job very well.

Noctis
  • 11,507
  • 3
  • 43
  • 82
Perry Neal
  • 765
  • 4
  • 7
1

For VB aficionados:

EnumStringValue = System.Enum.GetName(GetType(MyEnum), MyEnumValue)
GlennG
  • 2,982
  • 2
  • 20
  • 25
1

For me the easiest way to Convert an Enum to String and vice-versa is:

// Sample for Enum.ToString(String)
using System;

class Sample
{
    enum Colors {Red, Yellow = 12};

    public static void Main()
    {
    Colors myColor = Colors.Yellow;

    Console.WriteLine("Colors.Red = {0}", Colors.Red.ToString("d"));
    Console.WriteLine("Colors.Yellow = {0}", Colors.Yellow.ToString("d"));

    Console.WriteLine("{0}myColor = Colors.Yellow{0}", Environment.NewLine);

    Console.WriteLine("myColor.ToString(\"g\") = {0}", myColor.ToString("g"));
    Console.WriteLine("myColor.ToString(\"G\") = {0}", myColor.ToString("G"));

    Console.WriteLine("myColor.ToString(\"x\") = {0}", myColor.ToString("x"));
    Console.WriteLine("myColor.ToString(\"X\") = {0}", myColor.ToString("X"));

    Console.WriteLine("myColor.ToString(\"d\") = {0}", myColor.ToString("d"));
    Console.WriteLine("myColor.ToString(\"D\") = {0}", myColor.ToString("D"));

    Console.WriteLine("myColor.ToString(\"f\") = {0}", myColor.ToString("f"));
    Console.WriteLine("myColor.ToString(\"F\") = {0}", myColor.ToString("F"));
    }
}
/*
This example produces the following results:
Colors.Red = 0
Colors.Yellow = 12

myColor = Colors.Yellow

myColor.ToString("g") = Yellow
myColor.ToString("G") = Yellow
myColor.ToString("x") = 0000000C
myColor.ToString("X") = 0000000C
myColor.ToString("d") = 12
myColor.ToString("D") = 12
myColor.ToString("f") = Yellow
myColor.ToString("F") = Yellow
*/ 

Now to convert the selected string back to Enum you can just Parse it:

var myYellowEnum = Enum.Parse(typeof (Colors), "Yellow"); // Returns Yellow
rick
  • 479
  • 5
  • 14
0

This would work too.

    List<string> names = Enum.GetNames(typeof(MyEnum)).ToList();
Nic
  • 1,262
  • 2
  • 22
  • 42
0

ToString() gives the most obvious result from a readability perspective, while using Enum.GetName() requires a bit more mental parsing to quickly understand what its trying to do (unless you see the pattern all the time).

From a pure performance point of view, as already provided in @nawfal's answer, Enum.GetName() is better.

If performance is really your goal though, it would be even better to provide a look-up beforehand (using a Dictionary or some other mapping).

In C++/CLI, this would look like

Dictionary<String^, MyEnum> mapping;
for each (MyEnum field in Enum::GetValues(MyEnum::typeid))
{
    mapping.Add(Enum::GetName(MyEnum::typeid), field);
}

Comparison using an enum of 100 items and 1000000 iterations:

Enum.GetName: ~800ms
.ToString(): ~1600ms
Dictionary mapping: ~250ms

John Go-Soco
  • 886
  • 1
  • 9
  • 20
0

With new Roslyn warnings this question got me thinking. My research led me to 2 libraries. Both show better performance than the built-in .NET 5 methods ToString, GetName, etc. Take a look at benchmarks:

Enums.NET

FastEnum

Dharman
  • 30,962
  • 25
  • 85
  • 135
DerSkythe
  • 429
  • 6
  • 11
-3

Simple: enum names into a List:

List<String> NameList = Enum.GetNames(typeof(YourEnumName)).Cast<string>().ToList()
Brian
  • 3,653
  • 1
  • 22
  • 33