在C#中将字符串转换为枚举值的最佳方法是什么?
我有一个包含枚举值的HTML选择标记.发布页面时,我想获取值(将以字符串的形式)并将其转换为枚举值.
在一个理想的世界里,我可以这样做:
StatusEnum MyStatus = StatusEnum.Parse("Active");
但那不是有效的代码.
在.NET Core和.NET> 4中,有一个通用的解析方法:
Enum.TryParse("Active", out StatusEnum myStatus);
这还包括C#7的新内联out
变量,因此这将执行try-parse,转换为显式枚举类型并初始化+填充myStatus
变量.
如果您可以访问C#7和最新的.NET,这是最好的方法.
在.NET中它相当丑陋(直到4或以上):
StatusEnum MyStatus = (StatusEnum) Enum.Parse(typeof(StatusEnum), "Active", true);
我倾向于简化这个:
public static T ParseEnum(string value) { return (T) Enum.Parse(typeof(T), value, true); }
然后我可以这样做:
StatusEnum MyStatus = EnumUtil.ParseEnum("Active");
评论中建议的一个选项是添加一个扩展,这很简单:
public static T ToEnum(this string value) { return (T) Enum.Parse(typeof(T), value, true); } StatusEnum MyStatus = "Active".ToEnum ();
最后,如果无法解析字符串,您可能希望使用默认枚举:
public static T ToEnum(this string value, T defaultValue) { if (string.IsNullOrEmpty(value)) { return defaultValue; } T result; return Enum.TryParse (value, true, out result) ? result : defaultValue; }
这使得这个电话:
StatusEnum MyStatus = "Active".ToEnum(StatusEnum.None);
但是,我会小心地将这样的扩展方法添加到string
(没有命名空间控制)它将出现在所有实例上,string
无论它们是否包含枚举(因此1234.ToString().ToEnum(StatusEnum.None)
有效但无意义).通常最好避免使用仅在非常特定的上下文中应用的额外方法来混淆Microsoft的核心类,除非您的整个开发团队非常了解这些扩展的作用.
使用Enum.TryParse
(≥.NET4.0):
StatusEnum myStatus; Enum.TryParse("Active", out myStatus);
使用C#7.0的参数类型内联可以进一步简化:
Enum.TryParse("Active", out StatusEnum myStatus);
请注意,Enum.Parse()的性能很糟糕,因为它是通过反射实现的.(对于Enum.ToString也是如此,这是另一种方式.)
如果您需要在性能敏感的代码中将字符串转换为枚举,最好的办法是Enum.Parse()
在启动时创建并使用它来进行转换.
你正在寻找Enum.Parse.
SomeEnum enum = (SomeEnum)Enum.Parse(typeof(SomeEnum), "EnumValue");
您现在可以使用扩展方法:
public static T ToEnum(this string value, bool ignoreCase = true) { return (T) Enum.Parse(typeof (T), value, ignoreCase); }
您可以通过以下代码调用它们(这里FilterType
是一个枚举类型):
FilterType filterType = type.ToEnum();
object Enum.Parse(System.Type enumType, string value, bool ignoreCase);
所以,如果你有一个名为heart的枚举,它将如下所示:
enum Mood { Angry, Happy, Sad } // ... Mood m = (Mood) Enum.Parse(typeof(Mood), "Happy", true); Console.WriteLine("My mood is: {0}", m.ToString());
谨防:
enum Example { One = 1, Two = 2, Three = 3 }
Enum.(Try)Parse()
接受多个逗号分隔的参数,并将它们与二进制'或'组合|
.你不能禁用它,在我看来你几乎从不想要它.
var x = Enum.Parse("One,Two"); // x is now Three
即使Three
没有定义,x
仍然会得到int值3
.更糟糕的是:Enum.Parse()可以为你提供一个甚至没有为枚举定义的值!
我不想让用户自愿或不情愿地触发这种行为.
另外,正如其他人所提到的,对于大型枚举,性能不太理想,即可能值的数量是线性的.
我建议如下:
public static bool TryParse(string value, out T result) where T : struct { var cacheKey = "Enum_" + typeof(T).FullName; // [Use MemoryCache to retrieve or create&store a dictionary for this enum, permanently or temporarily. // [Implementation off-topic.] var enumDictionary = CacheHelper.GetCacheItem(cacheKey, CreateEnumDictionary , EnumCacheExpiration); return enumDictionary.TryGetValue(value.Trim(), out result); } private static Dictionary CreateEnumDictionary () { return Enum.GetValues(typeof(T)) .Cast () .ToDictionary(value => value.ToString(), value => value, StringComparer.OrdinalIgnoreCase); }
Enum.Parse是你的朋友:
StatusEnum MyStatus = (StatusEnum)Enum.Parse(typeof(StatusEnum), "Active");
您可以使用默认值扩展接受的答案以避免例外:
public static T ParseEnum(string value, T defaultValue) where T : struct { try { T enumValue; if (!Enum.TryParse(value, true, out enumValue)) { return defaultValue; } return enumValue; } catch (Exception) { return defaultValue; } }
然后你称之为:
StatusEnum MyStatus = EnumUtil.ParseEnum("Active", StatusEnum.None);
我们无法假设完全有效的输入,并且随着@ Keith的回答变化:
public static TEnum ParseEnum(string value) where TEnum : struct { TEnum tmp; if (!Enum.TryParse (value, true, out tmp)) { tmp = new TEnum(); } return tmp; }
// str.ToEnum() T static ToEnum (this string str) { return (T) Enum.Parse(typeof(T), str); }
将字符串解析为TEnum,不使用try/catch,也不使用.NET 4.5中的TryParse()方法
////// Parses string to TEnum without try/catch and .NET 4.5 TryParse() /// public static bool TryParseToEnum(string probablyEnumAsString_, out TEnum enumValue_) where TEnum : struct { enumValue_ = (TEnum)Enum.GetValues(typeof(TEnum)).GetValue(0); if(!Enum.IsDefined(typeof(TEnum), probablyEnumAsString_)) return false; enumValue_ = (TEnum) Enum.Parse(typeof(TEnum), probablyEnumAsString_); return true; }