一切都在标题中,我已经阅读了这个问题Enum.Parse() or Switch但是没有关于表现的内容。我的Enum大约有10个成员,我想知道哪个更快,切换或Enum.Parse()?
答案 0 :(得分:8)
切换总是更快,因为parse使用反射来获取成员的名称..但除非应用程序性能至关重要......(每秒数千次执行)..使用Enum.Parse使代码更易于维护
答案 1 :(得分:7)
美好而快速:
public static class EnumHelpers<TTarget>
{
static EnumHelpers()
{
Dict = Enum.GetNames(typeof(TTarget)).ToDictionary(x => x, x => (TTarget)Enum.Parse(typeof(TTarget), x), StringComparer.OrdinalIgnoreCase);
}
private static readonly Dictionary<string, TTarget> Dict;
public static TTarget Convert(string value)
{
return Dict[value];
}
}
答案 2 :(得分:4)
我使用表达式树构建了一个快速的“切换”版本。
public static Func<String, TEnum> GetParseEnumDelegate<TEnum>()
{
var eValue = Expression.Parameter(typeof(String), "value"); // (String value)
var tEnum = typeof(TEnum);
return
Expression.Lambda<Func<String, TEnum>>(
Expression.Block(tEnum,
Expression.Switch(tEnum, eValue,
Expression.Block(tEnum,
Expression.Throw(Expression.New(typeof(Exception).GetConstructor(Type.EmptyTypes))),
Expression.Default(tEnum)
),
null,
Enum.GetValues(tEnum).Cast<Object>().Select(v => Expression.SwitchCase(
Expression.Constant(v),
Expression.Constant(v.ToString())
)).ToArray()
)
), eValue
).Compile();
}
...
var parseEnum = GetParseEnumDelegate<YourEnum>();
YourEnum e = parseEnum("SomeEnumValue");
如果您需要非通用版本,则必须将交换机的结果从tEnum转换为typeof(Object)。
public static Func<String, Object> GetParseEnumDelegate(Type tEnum)
{
var eValue = Expression.Parameter(typeof(String), "value"); // (String value)
var tReturn = typeof(Object);
return
Expression.Lambda<Func<String, Object>>(
Expression.Block(tReturn,
Expression.Convert( // We need to box the result (tEnum -> Object)
Expression.Switch(tEnum, eValue,
Expression.Block(tEnum,
Expression.Throw(Expression.New(typeof(Exception).GetConstructor(Type.EmptyTypes))),
Expression.Default(tEnum)
),
null,
Enum.GetValues(tEnum).Cast<Object>().Select(v => Expression.SwitchCase(
Expression.Constant(v),
Expression.Constant(v.ToString())
)).ToArray()
), tReturn
)
), eValue
).Compile();
}
我做了几次性能测试,这个委托版本几乎和本机开关一样快。在我的场景中(包含10个项目的枚举),它比Enum.Parse()快5倍。
答案 3 :(得分:1)
正如@CaldasGSM回答的那样,最大的问题是Enum.Parse
方法内部正在发生的反思。此外,Enum.Parse内部实现中使用的IF的数量远远高于switch语句中的条件数,而不是计算该方法中的其他代码。所有这些都使它不如switch
。
如果您正在处理像您所说的少量项目,那么如果您使用的是Enum.Parse vs switch,则实际上没有显着差异。对于大量的项目来说,这是一个不同的故事。
但是,我要补充一点,Enum.Parse的另一个问题是,在解析不起作用的情况下,你必须使用try-catch块处理三种异常类型,这也会减慢代码的速度。
此外,在使用Enum.Parse时,您也不应忽略在object
类型中装入枚举值的成本,这也是性能损失。
要解决上述问题,更好的选择是使用较新的Enum.TryParse
API,这样可以更轻松地处理错误,并且还可以阻止装箱对象,因为它使用泛型。
以下是一个例子:
Items item;
if (!Enum.TryParse("First", true, out item))
{
// Handle error
}
答案 4 :(得分:1)
孤立地,switch
会更快。
但代码很少孤立地执行。通常,用户将输入一个值,或者您将从磁盘文件中加载它。 Enum
的全部目的是对字符串值进行符号表示,以便您可以更轻松地使用它。它还允许您验证输入的数据。
所以,让我们说你有一个枚举:
public enum Thing
{
Foo,
Bar,
Fooby,
Barby
}
有人给你一个字符串,应该代表其中一个。你写了一个switch语句:
switch (s)
{
case "Foo": break;
case "Bar": break;
case "Fooby": break;
case "Barby": break;
default : throw new ArgumentException();
}
如果用户输入&#34; foo&#34;会发生什么?你是否会拒绝它,因为案件不正确?非常不友好的行为。因此,您修改代码以对字符串执行ToLower()
,并修改您的案例以使用全部小写。
太疯狂了。如果使用Enum.TryParse
将其转换为枚举,则可以更容易理解和维护代码,然后使用枚举值执行需要完成的操作。
答案 5 :(得分:0)
使用开关(我更喜欢使用解析,因为它更易于维护)。
无论如何,过早优化是万恶之源。