在c#中将字符串转换为枚举值的最佳方法是什么?
我有一个包含枚举值的HTML选择标记。当页面被发布时,我想获取值(将以字符串的形式)并将其转换为相应的枚举值。
在理想的情况下,我可以这样做:
StatusEnum MyStatus = StatusEnum.Parse("Active");
但这不是有效的代码。
在c#中将字符串转换为枚举值的最佳方法是什么?
我有一个包含枚举值的HTML选择标记。当页面被发布时,我想获取值(将以字符串的形式)并将其转换为相应的枚举值。
在理想的情况下,我可以这样做:
StatusEnum MyStatus = StatusEnum.Parse("Active");
但这不是有效的代码。
当前回答
public TEnum ToEnum<TEnum>(this string value, TEnum defaultValue){
if (string.IsNullOrEmpty(value))
return defaultValue;
return Enum.Parse(typeof(TEnum), value, true);}
其他回答
你现在可以使用扩展方法了:
public static T ToEnum<T>(this string value, bool ignoreCase = true)
{
return (T) Enum.Parse(typeof (T), value, ignoreCase);
}
你可以通过下面的代码调用它们(在这里,FilterType是一个枚举类型):
FilterType filterType = type.ToEnum<FilterType>();
请注意:
enum Example
{
One = 1,
Two = 2,
Three = 3
}
Enum.(Try)Parse()接受多个逗号分隔的参数,并将它们与二进制'或' | '组合。你不能禁用这个,在我看来,你几乎从来都不想要它。
var x = Enum.Parse("One,Two"); // x is now Three
即使没有定义3,x仍然会得到int值3。更糟糕的是:枚举. parse()可以给你一个甚至没有为枚举定义的值!
我不想经历用户自愿或不情愿触发这种行为的后果。
此外,正如其他人所提到的,对于大型枚举(即可能值的数量呈线性),性能不太理想。
我的建议如下:
public static bool TryParse<T>(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<T>, EnumCacheExpiration);
return enumDictionary.TryGetValue(value.Trim(), out result);
}
private static Dictionary<string, T> CreateEnumDictionary<T>()
{
return Enum.GetValues(typeof(T))
.Cast<T>()
.ToDictionary(value => value.ToString(), value => value, StringComparer.OrdinalIgnoreCase);
}
对于性能,这可能会有所帮助:
private static Dictionary<Type, Dictionary<string, object>> dicEnum = new Dictionary<Type, Dictionary<string, object>>();
public static T ToEnum<T>(this string value, T defaultValue)
{
var t = typeof(T);
Dictionary<string, object> dic;
if (!dicEnum.ContainsKey(t))
{
dic = new Dictionary<string, object>();
dicEnum.Add(t, dic);
foreach (var en in Enum.GetValues(t))
dic.Add(en.ToString(), en);
}
else
dic = dicEnum[t];
if (!dic.ContainsKey(value))
return defaultValue;
else
return (T)dic[value];
}
我们不能假设输入是完全有效的,于是就用了@Keith的答案的变体:
public static TEnum ParseEnum<TEnum>(string value) where TEnum : struct
{
TEnum tmp;
if (!Enum.TryParse<TEnum>(value, true, out tmp))
{
tmp = new TEnum();
}
return tmp;
}
我发现这里没有考虑具有EnumMember值的enum值的情况。我们开始吧:
using System.Runtime.Serialization;
public static TEnum ToEnum<TEnum>(this string value, TEnum defaultValue) where TEnum : struct
{
if (string.IsNullOrEmpty(value))
{
return defaultValue;
}
TEnum result;
var enumType = typeof(TEnum);
foreach (var enumName in Enum.GetNames(enumType))
{
var fieldInfo = enumType.GetField(enumName);
var enumMemberAttribute = ((EnumMemberAttribute[]) fieldInfo.GetCustomAttributes(typeof(EnumMemberAttribute), true)).FirstOrDefault();
if (enumMemberAttribute?.Value == value)
{
return Enum.TryParse(enumName, true, out result) ? result : defaultValue;
}
}
return Enum.TryParse(value, true, out result) ? result : defaultValue;
}
枚举的例子是:
public enum OracleInstanceStatus
{
Unknown = -1,
Started = 1,
Mounted = 2,
Open = 3,
[EnumMember(Value = "OPEN MIGRATE")]
OpenMigrate = 4
}