将枚举转换为字符串


163

在.NET 3.5中将枚举转换为字符串的首选方法是哪种?

  • 枚举
  • 枚举格式
  • ToString

为什么我要选择其中之一?一个人表现更好吗?


10
我搜索了,但找不到重复项。如果您可以提供链接,我将删除此问题。
埃里克·韦尔瑙

1
有时,使用switch语句不是最佳实践(当您有大量枚举时),可以改用Dict <>
Guy L

1
如果要获得更好的性能,可以使用本文codeproject.com/KB/dotnet/enum.aspx中描述的类。用法看起来像这样Enum <YourEnum> .ToString(yourValue)或Enum <YourEnum> .ToString((int)yourValue)
ideafixxxer 2011年

5
编码不破坏点融合是尾巴摇动狗的缩影。软件生产商并不认为,“让我们成为一个出色的应用程序,让dotfuscator可以做些事情。” 存在Dofuscator可以帮助促进软件开发。如果做不到,那就可以!
micahhoover

Answers:


125

从C#6开始,获取枚举名称的最佳方法是new nameof运算符:

nameof(MyEnum.EnumValue);

// Ouputs
> "EnumValue"

这在编译时有效,枚举被编译结果中的字符串替换,这意味着这是最快的方法。

如果您认为混淆枚举名称是有价值的或重要的,则枚举名称的任何使用都会干扰代码的混淆,这可能是另一个问题。


11
这值得更多关注。尽管存在明显的局限性,即需要编译时输入。我认为,应尽可能选择此方法。“重命名”和“查找所有引用”也将其考虑在内,有可能避免使用魔术字符串和重复的常量。
Timo

1
因此,我猜想在运行时定义枚举值时它不起作用?例如:MyEnum variableEnum; variableEnum = setEnumValueMethod(); nameof(variableEnum);
Maxter

1
@Maxter不,nameof(variableEnum)将是"variableEnum"。它(在生成时)反映字段/属性/参数/变量的名称而不是
基思

嗯 不幸的是,如果这样做,将无法正常工作:var someEnumvalue = SomeEnum.FooBar; nameof(someEnumvalue);
Squibly

@可以,是的,它将返回"someEnumValue",而您需要nameof(SomeEnum.FooBar)获取"FooBar"
基思

93

适用于我们的项目...

public static String convertToString(this Enum eff)
{
    return Enum.GetName(eff.GetType(), eff);
}

public static EnumType converToEnum<EnumType>(this String enumValue)  
{
    return (EnumType) Enum.Parse(typeof(EnumType), enumValue);
}

7
Enum.GetName将该值作为对象参数。这意味着该值将被装箱,这将浪费CPU资源在分配和垃圾回收上。如果这样做很长时间,则Enum.GetName的吞吐量将比在字典中缓存值并在其中查找名称要低得多。
2014年

@Ran那么解决方案是什么呢?
shaijut

这应该是答案
可能是

使我的项目变慢。toString()更快。
d2k2

29

在我的测试中,Enum.GetName速度更快且获得了可观的利润。内部ToString通话Enum.GetName .NET 4.0的中,要点:

public override String ToString()
{
     return Enum.InternalFormat((RuntimeType)GetType(), GetValue());
}

private static String InternalFormat(RuntimeType eT, Object value)
{
    if (!eT.IsDefined(typeof(System.FlagsAttribute), false))
    {
        String retval = GetName(eT, value); //<== the one
        if (retval == null)
            return value.ToString();
        else
            return retval;
    }
    else
    {
        return InternalFlagsFormat(eT, value);
    }
}

我不能说这是确定的原因,但是测试表明一个比另一个要快。这两个调用都涉及装箱(实际上,它们是反射调用,实际上是在检索字段名称),并且喜欢起来可能很慢。

测试设置:具有8个值的枚举,否。迭代次数= 1000000

结果:Enum.GetName => 700 ms,ToString => 2000 ms

如果速度不明显,那么我将不在乎和使用ToString它,因为它可以提供更加清晰的通话。对比

Enum.GetName(typeof(Bla), value)

value.ToString()

25

枚举GetName(...)

这是最优雅的方法。

var enumValueString = Enum.GetName(typeof (MyEnum), MyEnum.MyValue);

尽管我认为呼叫.ToString()更短,但我认为它没有任何问题。

var enumValueString = MyEnum.MyValue.ToString();

使用新的C#6语法,您可以使用:

nameof(MyEnum.MyValue)

20

所有这些最终在内部调用了称为的方法InternalGetValueAsStringToString和之间的区别GetNameGetName必须首先验证以下几点:

  1. 您输入的类型不为空。
  2. 您输入的类型实际上是一个枚举。
  3. 您传入的值不为null。
  4. 您传入的值是枚举实际上可以用作其基础类型的类型,或者是枚举本身的类型。它使用GetType该值进行检查。

.ToString不必担心上述任何问题,因为它是在类本身的实例上调用的,而不是在传入版本中调用的,因此,由于该.ToString方法没有相同的验证问题作为静态方法,我将得出结论,这.ToString是将值作为字符串获取的最快方法。


2
您在哪里检查这些?什么是程序集版本?我得到非常不同的结果。
nawfal 2013年

17

最好的发现是MSDN上的这个不相关的问题,其中包含一个可回答该问题的XML代码段。这些方法中的任何一个都有相同的缺陷:它们调用enum.toString(),使用Dotfuscation时无法正常工作。其他问题似乎与间接装箱(GetName和Format)有关。不幸的是,我找不到使用以上任何一种性能的原因。

xml代码段改写

将装箱的枚举传递给string.Format()或任何其他函数都可能导致enum.ToString()被调用。点混淆时会引起问题。你不应该使用enum.ToString()enum.GetNames()enum.GetName()enum.Format()enum.Parse()以枚举转换为字符串。而是使用switch语句,并在必要时还对名称进行国际化。


16

Enum.GetName()

Format()实际上只是GetName()一些格式化功能的包装(InternalGetValueAsString()确切地说是)。ToString()与几乎相同Format()。我认为这GetName()是最好的选择,因为对于任何阅读源的人来说,这样做是显而易见的。


8

我创建了一个“描述”扩展方法并将其附加到枚举,以便我可以得到真正的用户友好名称,包括空格和大小写。我从未喜欢将枚举值本身用作可显示的文本,因为我们开发人员使用它来创建更具可读性的代码。它不旨在用于UI显示。我希望能够更改UI,而无需遍历和更改枚举。


6

我不知道“首选”方法是什么(问100个人并获得100种不同的意见),但是却做了最简单,最有效的方法。 GetName可以,但是需要更多的击键。 ToString()似乎做得很好。


1

对于VB爱好者:

EnumStringValue = System.Enum.GetName(GetType(MyEnum), MyEnumValue)

0

这也可以。

    List<string> names = Enum.GetNames(typeof(MyEnum)).ToList();

0

ToString()从可读性的角度来看,它提供了最明显的结果,而使用则Enum.GetName()需要更多的心理分析才能快速了解其尝试执行的操作(除非您始终看到该模式)。

从纯性能的角度来看,@ nawfal的答案已经提供了Enum.GetName()更好的方法。

如果性能确实是您的目标,那么最好事先提供查找(使用字典或其他映射)。

在C ++ / CLI中,这看起来像

Dictionary<String^, MyEnum> mapping;
for each (MyEnum field in Enum::GetValues(MyEnum::typeid))
{
    mapping.Add(Enum::GetName(MyEnum::typeid), field);
}

使用100个项目的枚举和1000000次迭代进行比较:

Enum.GetName:〜800ms
.ToString():〜1600ms
字典映射:〜250ms


-2

简单:将名称枚举到列表中:

List<String> NameList = Enum.GetNames(typeof(YourEnumName)).Cast<string>().ToList()

嗨,@ Brian,我认为您不需要强制转换GetNames()的输出
Nic
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.