要将字符串转换为枚举,以下哪种方式更好?
此代码:
colorEnum color = (colorEnum)Enum.Parse(typeof(colorEnum), "Green");
或者:
string colorString = ...
colorEnum color;
switch (colorString)
{
case "Green":
color = colorEnum.Green;
break;
case "Red":
color = colorEnum.Red;
break;
case "Orange":
color = colorEnum.Orange;
break;
....
}
答案 0 :(得分:8)
您应该使用Enum.TryParse,如果失败,您可以正确处理错误。
样品:
ColorsEnum colorValue;
if (Enum.TryParse(colorString, out colorValue))
if (Enum.IsDefined(typeof(Colors), colorValue) | colorValue.ToString().Contains(","))
Console.WriteLine("Converted '{0}' to {1}.", colorString, colorValue.ToString());
else
Console.WriteLine("{0} is not an underlying value of the Colors enumeration.", colorString);
else
Console.WriteLine("{0} is not a member of the Colors enumeration.", colorString);
答案 1 :(得分:7)
(警告:包含我自己的开源库的插件......)
就个人而言,我会使用Unconstrained Melody,最终会使用更清晰,更安全的代码:
ColorEnum color = Enums.ParseName<ColorEnum>(text);
如果您怀疑它可能无效,可以使用TryParseName
。显然这需要一个额外的库,但希望你也能找到其他有用的东西:)
Enum.TryParse
比其他内置选项更好,但是:
Enum.TryParse<int>(...)
仍将编译;无约束的旋律真的只允许枚举类型Enum.TryParse
也将解析“1”(或转换为字符串时的数值) - 如果你真的只是期望的名字,我认为最好只用接受名称我绝对不会切换字符串值 - 这意味着如果重命名枚举值,您必须记住重命名案例值。
答案 2 :(得分:4)
string myColorStr = "red";
colorEnum myColor;
if(!Enum.TryParse<colorEnum>(myColorStr, true, out myColor))
{
throw new InvalidOperationException("Unknown color " + myColorStr);
}
答案 3 :(得分:2)
1)好多了。这是更清洁的代码。你在一行中做了多少2)。此外,它不容易出错。当你向colorEnum
添加另一个项目时,你需要记住扩展2)wheras 1)才能正常工作。
您可能还需要对Enum.Parse
进行错误处理。
答案 4 :(得分:2)
仅限于可读性和可维护性。如果你扩展枚举,你不需要做额外的工作,有2个你需要在switch语句中添加更多的情况
答案 5 :(得分:2)
因为你添加了标签'performance',所以我会选择开关 是的,当您重命名/添加/删除枚举中的任何内容时,您将不得不更改案例。那太糟糕了。 Enum.Parse / TryParse的任何变体都使用了很多奇怪的代码和一些反射,只需看一下ILSpy等函数。然后还有接受“-12354”的问题,甚至是逗号分隔的有效名称列表(导致所有这些名称一起被OR化),即使枚举没有[Flags]属性。
作为替代方案,您可以创建一个将枚举名称转换为值的字典。它实际上应该比开关更快,因为字符串上的开关也会通过字典但你保存实际的开关部分。
显然,这两种方式都需要比enum.parse和变体更多的维护;是否值得它取决于你,因为在我们所有人中,只有你对项目有足够的了解才能使性能/编码时间权衡。
答案 6 :(得分:1)
除了两个不同的代码片段没有做同样的事情之外,我会用这个:
colorEnum color;
if (!colorEnum.TryParse(colorString, true, out color)
color = colorEnum.Green; // Or whatever default value you wish to have.
如果你没有.NET 4.0,那么我会做这样的事情:
public static TEnum ToEnum<TEnum>(this string strEnumValue, TEnum defaultValue)
{
if (!Enum.IsDefined(typeof(TEnum), strEnumValue))
return defaultValue;
return (TEnum)Enum.Parse(typeof(TEnum), strEnumValue);
}
这是Extension Method到string
。
答案 7 :(得分:1)
就个人而言,虽然我对非性能场景的Enum.Parse解决方案完全没问题(阅读:偶尔运行此功能一次......并且有很多这样的场景可以肯定),我无法忍受当这个函数需要一次在数百/千多个枚举值的循环中执行时,可能涉及一些反射类型方法的想法。 GACK!
所以以下是一个解决方案,可以获得两个世界中最好的一些。
只需在启动时检索枚举的所有值,或者什么不是,只要它最适合您(下面是一种方法),然后用它们构造一个词典。
private static Dictionary<string, Color> colorDictionary;
public static Dictionary<string, Color> ColorDictionary
{
get
{
if (colorDictionary== null) {
colorDictionary = new Dictionary<string, Color>();
var all = Enum.GetValues(typeof(Color)).OfType<Color>();
foreach (var val in all)
dict.Add(val.ToString(), val);
}
return colorDictionary;
}
}
答案 8 :(得分:0)
我发现开关变体很糟糕,因为每次更改枚举时都必须修改开关。
我喜欢使用属于你的枚举的TryParse。所以你可以像这样使用它
string colorString = .....
colorEnum color;
colorEnum.TryParse(colorString, out color);
或者如果你不关心字符串的情况
colorEnum.TryParse(colorString, true, out color);
如果字符串是有效的枚举,则TryParse
的返回值为true,否则为false。
答案 9 :(得分:0)
从性能的角度来看,由于枚举是作为静态字段实现的,因此parse方法可能最终会对枚举类型进行反射,并尝试一种可能比这种情况更快的GetField方法。另一方面,如果90%的情况,颜色为绿色,则情况会非常快......请注意,CLR有时会在内部重新排列代码,根据统计信息更改案例的顺序(实际上,我是不确定它是否那样,但文件声称它可以)。
答案 10 :(得分:0)
我使用以下内容,它可以为您提供所有类型的安全性,同时在向Enum添加新值时仍然不会失败,它也非常快。
public static colorEnum? GetColorFromString(string colorString)
{
colorEnum? retVal = null;
if(Enum.IsDefined(typeof(colorEnum), colorString))
retVal = (colorEnum)Enum.Parse(typeof(colorEnum), colorString);
return retVal;
}
我在枚举中使用8个项目的测试显示这种方式比切换方法更快。
否则你可以使用(非常慢的方式):
public static colorEnum? GetColorFromString(string colorString)
{
foreach (colorEnum col in Enum.GetValues(typeof(colorEnum)))
{
if (col.ToString().Equals(colorString))
{
return col;
}
}
return null;
}