【问题标题】:Enum to Dictionary in C#在 C# 中枚举到字典
【发布时间】:2011-07-31 19:42:45
【问题描述】:

我已经在网上搜索过这个,但我找不到我正在寻找的答案。

基本上我有以下枚举:

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

如何将此枚举转换为 Dictionary 以便它存储在以下 Dictionary 中?

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

myDic 看起来像这样:

1, itemA
2, itemB
3, itemC

有什么想法吗?

【问题讨论】:

  • 为什么首先需要这样做?我不禁想知道是否没有更好的方法来解决您使用这本词典解决的任何问题。
  • @juharr 26 到目前为止,其他人发现它很有用 - 你看到了吗?我需要将它传递给 UI 层,这样我基本上可以在 javascript 中使用枚举(在下拉列表中),而无需对值进行硬编码。

标签: c# dictionary collections enums


【解决方案1】:

另一种基于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.Ordinal).</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());
    }

【讨论】:

    【解决方案2】:

    试试:

    var dict = Enum.GetValues(typeof(fooEnumType))
                   .Cast<fooEnumType>()
                   .ToDictionary(t => (int)t, t => t.ToString() );
    

    【讨论】:

    • 我知道 Enum.ToString() 与它有关 :)
    • +1 这其实是这个问题最直接的答案。我已经看到了方法扩展和反射的方法,但是如果你可以用 linq 来实现,那就没有必要了。
    • 我正在尝试将其翻译到 VB.net,但我似乎遇到了 .Cast&lt;typFoo&gt;() 行的问题。我尝试了.Cast(Of typeFoo),但收到了无效的强制转换异常。
    • 修复了!我试图使用Enum.GetNames() 而不是Enum.GetValues()
    • 这正是我想要的。
    【解决方案3】:

    +1 到Ani。这是VB.NET版本

    这是 Ani 答案的 VB.NET 版本:

    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
    

    其他示例

    就我而言,我想保存重要目录的路径并将它们存储在我的 web.config 文件的 AppSettings 部分。然后我创建了一个枚举来表示这些 AppSettings 的键......但是我的前端工程师需要访问我们外部 JavaScript 文件中的这些位置。因此,我创建了以下代码块并将其放置在我们的主母版页中。现在,每个新的 Enum 项目都会自动创建一个相应的 JavaScript 变量。这是我的代码块:

        <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>
    

    注意:在此示例中,我使用枚举的名称作为键(而不是 int 值)。

    【讨论】:

      【解决方案4】:
      • 扩展方法
      • 常规命名
      • 一行
      • C# 7 返回语法(但您可以在旧的 C# 版本中使用方括号)
      • 如果类型不是System.Enum,则抛出ArgumentException,感谢Enum.GetValues
      • IntelliSense 将仅限于结构(尚无 enum 约束可用)
      • 如果需要,允许您使用枚举索引到字典中。
      public static Dictionary<T, string> ToDictionary<T>() where T : struct
        => Enum.GetValues(typeof(T)).Cast<T>().ToDictionary(e => e, e => e.ToString());
      

      【讨论】:

        【解决方案5】:

        用途:

        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;
            }
        }
        

        用法:

        public enum typFoo : int
        {
           itemA = 1,
           itemB = 2,
           itemC = 3
        }
        
        var mydic = EnumHelper.ConvertToDictionary<typFoo>();
        

        【讨论】:

          【解决方案6】:

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

          foreach( typFoo foo in Enum.GetValues(typeof(typFoo)) )
          {
              mydic.Add((int)foo, foo.ToString());
          }
          

          【讨论】:

          • 如果多个枚举条目可能具有相同的值,请谨慎使用Enum.GetValues 的任何答案。可以理解,这种情况是一种蚂蚁模式,但它会导致异常/问题。
          • 如果你不知道类型,另一种方法(仍然容易出现相同的多个枚举条目问题),给定Type tFoo = typeof(typFoo)Enum.GetNames(tFoo).ToDictionary(t =&gt; (int)System.Enum.Parse(tFoo, t), t =&gt; t)
          【解决方案7】:

          调整Ani's answer,使其可以用作通用方法(感谢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());
          }
          

          【讨论】:

          • 你能用(int)(object)t代替(int)Convert.ChangeType(t, t.GetType())吗?它编译。 ChangeType 返回一个object,所以我认为你的拳击是两种方式。
          • 好吧,只要你的底层类型是int。例如,如果它是short,这将不起作用。 (但是你的字典应该被修改为返回一个short。)
          • 如果您有兴趣,您可以在下面看到我的回答,了解我是如何解决这个问题的。
          【解决方案8】:

          使用反射:

          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);
          }
          

          【讨论】:

          • 这可能是最复杂的方法;-)。
          • 啊哈哈是的......但这是我迄今为止唯一知道的方法。 :D xD :P
          • 性能影响是什么?在序列化期间使用反射是一个真正的性能杀手。
          【解决方案9】:

          如果您只需要名称,则根本不必创建该字典。

          这会将 enum 转换为 int:

           int pos = (int)typFoo.itemA;
          

          这会将 int 转换为 enum:

            typFoo foo = (typFoo) 1;
          

          这将返回它的名称:

           ((typFoo) i).toString();
          

          【讨论】:

          • 他不是在问如何在inttypFoo 之间转换。
          【解决方案10】:

          您可以枚举枚举描述符:

          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);
          }
          

          这应该将每个项目的值和名称放入您的字典中。

          【讨论】:

          • 这是处理多个枚举条目具有相同值的情况的唯一答案。也许这是一种反模式,但这至少可以帮助识别案例,而不是返回重复的条目,
          猜你喜欢
          • 2010-10-15
          • 1970-01-01
          • 2022-01-23
          • 1970-01-01
          • 2014-11-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多