在 C# 中枚举到字典
Posted
技术标签:
【中文标题】在 C# 中枚举到字典【英文标题】:Enum to Dictionary in 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 中使用枚举(在下拉列表中),而无需对值进行硬编码。 【参考方案1】:另一种基于Arithmomaniac's example的扩展方法:
/// <summary>
/// Returns a Dictionary<int, string> 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<typFoo>()
行的问题。我尝试了.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 => (int)System.Enum.Parse(tFoo, t), t => 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();
【讨论】:
他不是在问如何在int
和typFoo
之间转换。【参考方案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);
这应该将每个项目的值和名称放入您的字典中。
【讨论】:
这是处理多个枚举条目具有相同值的情况的唯一答案。也许这是一种反模式,但这至少可以帮助识别案例,而不是返回重复的条目,以上是关于在 C# 中枚举到字典的主要内容,如果未能解决你的问题,请参考以下文章