68

I have searched this online, but I can't find the answer I am looking for.

Basically I have the following enum:

public enum typFoo : int
{
   itemA : 1,
   itemB : 2
   itemC : 3
}

How can I convert this enum to Dictionary so that it stores in the following Dictionary?

Dictionary<int,string> myDic = new Dictionary<int,string>();

And myDic would look like this:

1, itemA
2, itemB
3, itemC

Any ideas?

Ola Ström
  • 917
  • 1
  • 8
  • 23
daehaai
  • 5,155
  • 9
  • 38
  • 57
  • 1
    Why do you need to do this in the first place? I cannot help but wonder if there isn't a better way to solve whatever problem you are using this dictionary for. – juharr Apr 07 '11 at 16:20
  • 3
    @juharr 26 other people find it useful so far - do you see it yet? I need to pass it down to the UI layer so I can basically use the enum in javascript (in a dropdown) without hardcoding the values. – PandaWood Dec 12 '16 at 23:38

10 Answers10

177

Try:

var dict = Enum.GetValues(typeof(fooEnumType))
               .Cast<fooEnumType>()
               .ToDictionary(t => (int)t, t => t.ToString() );
Community
  • 1
  • 1
Ani
  • 103,292
  • 21
  • 241
  • 294
54

See: How do I enumerate an enum in C#?

foreach( typFoo foo in Enum.GetValues(typeof(typFoo)) )
{
    mydic.Add((int)foo, foo.ToString());
}
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Zhais
  • 1,423
  • 11
  • 18
  • Careful with any answer using `Enum.GetValues` if there is a chance that multiple enum entries have the same value. Understandably this case is an ant-pattern, but it will cause an exception/problem. – Andrew Hanlon Mar 31 '16 at 20:14
  • If you don't know the type, an alternative way of doing this (still prone to the same multiple enum entries issue), given `Type tFoo = typeof(typFoo)` is `Enum.GetNames(tFoo).ToDictionary(t => (int)System.Enum.Parse(tFoo, t), t => t)` – saluce Apr 18 '18 at 15:19
16

Adapting Ani's answer so that it can be used as a generic method (thanks, toddmo):

public static Dictionary<int, string> EnumDictionary<T>()
{
    if (!typeof(T).IsEnum)
        throw new ArgumentException("Type must be an enum");
    return Enum.GetValues(typeof(T))
        .Cast<T>()
        .ToDictionary(t => (int)(object)t, t => t.ToString());
}
Community
  • 1
  • 1
Arithmomaniac
  • 3,978
  • 2
  • 31
  • 52
  • 2
    could you just do `(int)(object)t` instead of `(int)Convert.ChangeType(t, t.GetType())`? It compiles. `ChangeType` returns an `object`, so I think your boxing either way. – toddmo May 14 '17 at 21:00
  • Well, as long as your underlying type is `int`. If it's `short`, for example, this wouldn't work. (But then your Dictionary should be modified to return a `short` anyways.) – Arithmomaniac May 15 '17 at 15:34
  • You can see my answer below on how I solved that if you're interested. – toddmo May 15 '17 at 17:46
6
  • Extension method
  • Conventional naming
  • One line
  • C# 7 return syntax (but you can use brackets in those old legacy versions of C#)
  • Throws an ArgumentException if the type is not System.Enum, thanks to Enum.GetValues
  • IntelliSense will be limited to structs (no enum constraint is available yet)
  • Allows you to use enum to index into the dictionary, if desired.
public static Dictionary<T, string> ToDictionary<T>() where T : struct
  => Enum.GetValues(typeof(T)).Cast<T>().ToDictionary(e => e, e => e.ToString());
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
toddmo
  • 16,852
  • 9
  • 86
  • 91
4

Another extension method that builds on Arithmomaniac's example:

    /// <summary>
    /// Returns a Dictionary&lt;int, string&gt; of the parent enumeration. Note that the extension method must
    /// be called with one of the enumeration values, it does not matter which one is used.
    /// Sample call: var myDictionary = StringComparison.Ordinal.ToDictionary().
    /// </summary>
    /// <param name="enumValue">An enumeration value (e.g. StringComparison.Ordianal).</param>
    /// <returns>Dictionary with Key = enumeration numbers and Value = associated text.</returns>
    public static Dictionary<int, string> ToDictionary(this Enum enumValue)
    {
        var enumType = enumValue.GetType();
        return Enum.GetValues(enumType)
            .Cast<Enum>()
            .ToDictionary(t => (int)(object)t, t => t.ToString());
    }
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
j2associates
  • 830
  • 6
  • 14
3

+1 to Ani. Here's the VB.NET version

Here's the VB.NET version of Ani's answer:

Public Enum typFoo
    itemA = 1
    itemB = 2
    itemC = 3
End Enum

Sub example()

    Dim dict As Dictionary(Of Integer, String) = System.Enum.GetValues(GetType(typFoo)) _
                                                 .Cast(Of typFoo)() _
                                                 .ToDictionary(Function(t) Integer.Parse(t), Function(t) t.ToString())
    For Each i As KeyValuePair(Of Integer, String) In dict
        MsgBox(String.Format("Key: {0}, Value: {1}", i.Key, i.Value))
    Next

End Sub

Additional example

In my case, I wanted to save the path of important directories and store them in my web.config file's AppSettings section. Then I created an enum to represent the keys for these AppSettings...but my front-end engineer needed access to these locations in our external JavaScript files. So, I created the following code-block and placed it in our primary master page. Now, each new Enum item will auto-create a corresponding JavaScript variable. Here's my code block:

    <script type="text/javascript">
        var rootDirectory = '<%= ResolveUrl("~/")%>';
        // This next part will loop through the public enumeration of App_Directory and create a corresponding JavaScript variable that contains the directory URL from the web.config.
        <% Dim App_Directories As Dictionary(Of String, App_Directory) = System.Enum.GetValues(GetType(App_Directory)) _
                                                                   .Cast(Of App_Directory)() _
                                                                   .ToDictionary(Of String)(Function(dir) dir.ToString)%>
        <% For Each i As KeyValuePair(Of String, App_Directory) In App_Directories%>
            <% Response.Write(String.Format("var {0} = '{1}';", i.Key, ResolveUrl(ConfigurationManager.AppSettings(i.Value))))%>
        <% next i %>
    </script>

NOTE: In this example, I used the name of the enum as the key (not the int value).

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Lopsided
  • 3,681
  • 1
  • 23
  • 43
3

You can enumerate over the enum descriptors:

Dictionary<int, string> enumDictionary = new Dictionary<int, string>();

foreach(var name in Enum.GetNames(typeof(typFoo))
{
    enumDictionary.Add((int)((typFoo)Enum.Parse(typeof(typFoo)), name), name);
}

That should put the value of each item and the name into your dictionary.

Tejs
  • 38,896
  • 8
  • 64
  • 81
  • 1
    This is the only answer that handles cases where multiple enum entries have the same value. Maybe that is an anti-pattern but this can at least help identify the case, rather than returning duplicate entries, – Andrew Hanlon Mar 31 '16 at 20:12
2

Use:

public static class EnumHelper
{
    public static IDictionary<int, string> ConvertToDictionary<T>() where T : struct
    {
        var dictionary = new Dictionary<int, string>();

        var values = Enum.GetValues(typeof(T));

        foreach (var value in values)
        {
            int key = (int) value;

            dictionary.Add(key, value.ToString());
        }

        return dictionary;
    }
}

Usage:

public enum typFoo : int
{
   itemA = 1,
   itemB = 2,
   itemC = 3
}

var mydic = EnumHelper.ConvertToDictionary<typFoo>();
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Arif
  • 4,274
  • 3
  • 40
  • 64
1

Using reflection:

Dictionary<int,string> mydic = new Dictionary<int,string>();

foreach (FieldInfo fi in typeof(typFoo).GetFields(BindingFlags.Public | BindingFlags.Static))
{
    mydic.Add(fi.GetRawConstantValue(), fi.Name);
}
Cipi
  • 10,430
  • 9
  • 43
  • 59
0

If you need only the name you don't have to create that dictionary at all.

This will convert enum to int:

 int pos = (int)typFoo.itemA;

This will convert int to enum:

  typFoo foo = (typFoo) 1;

And this will retrun you the name of it:

 ((typFoo) i).toString();