在c#中将字符串转换为枚举值的最佳方法是什么?
我有一个包含枚举值的HTML选择标记。当页面被发布时,我想获取值(将以字符串的形式)并将其转换为相应的枚举值。
在理想的情况下,我可以这样做:
StatusEnum MyStatus = StatusEnum.Parse("Active");
但这不是有效的代码。
在c#中将字符串转换为枚举值的最佳方法是什么?
我有一个包含枚举值的HTML选择标记。当页面被发布时,我想获取值(将以字符串的形式)并将其转换为相应的枚举值。
在理想的情况下,我可以这样做:
StatusEnum MyStatus = StatusEnum.Parse("Active");
但这不是有效的代码。
当前回答
我开始使用这种方法。性能似乎还可以,但它需要一些样板代码设置。
public enum StatusType {
Success,
Pending,
Rejected
}
static class StatusTypeMethods {
public static StatusType GetEnum(string type) {
switch (type) {
case nameof(StatusType.Success): return StatusType.Success;
case nameof(StatusType.Pending): return StatusType.Pending;
case nameof(StatusType.Rejected): return StatusType.Rejected;
default:
throw new ArgumentOutOfRangeException(nameof(type), type, null);
};
}
}
之后,你可以这样使用它:
StatusType = StatusType.GetEnum("Success");
其他回答
您可以使用默认值扩展接受的答案以避免异常:
public static T ParseEnum<T>(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);
如果默认值不是enum,则为enum。TryParse将失败并抛出一个被捕获的异常。
在我们的代码中许多地方使用了这个函数多年之后,也许添加这个操作降低性能的信息是很好的!
<Extension()>
Public Function ToEnum(Of TEnum)(ByVal value As String, ByVal defaultValue As TEnum) As TEnum
If String.IsNullOrEmpty(value) Then
Return defaultValue
End If
Return [Enum].Parse(GetType(TEnum), value, True)
End Function
请注意:
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);
}
试试这个例子:
public static T GetEnum<T>(string model)
{
var newModel = GetStringForEnum(model);
if (!Enum.IsDefined(typeof(T), newModel))
{
return (T)Enum.Parse(typeof(T), "None", true);
}
return (T)Enum.Parse(typeof(T), newModel.Result, true);
}
private static Task<string> GetStringForEnum(string model)
{
return Task.Run(() =>
{
Regex rgx = new Regex("[^a-zA-Z0-9 -]");
var nonAlphanumericData = rgx.Matches(model);
if (nonAlphanumericData.Count < 1)
{
return model;
}
foreach (var item in nonAlphanumericData)
{
model = model.Replace((string)item, "");
}
return model;
});
}
在这个示例中,您可以发送每个字符串,并设置您的Enum。如果你的Enum有你想要的数据,返回你的Enum类型。
public static T ParseEnum<T>(string value) //function declaration
{
return (T) Enum.Parse(typeof(T), value);
}
Importance imp = EnumUtil.ParseEnum<Importance>("Active"); //function call
==================== 一个完整的程序 ====================
using System;
class Program
{
enum PetType
{
None,
Cat = 1,
Dog = 2
}
static void Main()
{
// Possible user input:
string value = "Dog";
// Try to convert the string to an enum:
PetType pet = (PetType)Enum.Parse(typeof(PetType), value);
// See if the conversion succeeded:
if (pet == PetType.Dog)
{
Console.WriteLine("Equals dog.");
}
}
}
-------------
Output
Equals dog.