26

有谁知道如何将枚举值转换为人类可读的值?

例如:

ThisIsValueA 应该是“这是值 A”。

4

8 回答 8

18

从很久以前某个 Ian Horwill 在博客文章中留下的 vb 代码片段转换它......我已经成功地在生产中使用了它。

    /// <summary>
    /// Add spaces to separate the capitalized words in the string, 
    /// i.e. insert a space before each uppercase letter that is 
    /// either preceded by a lowercase letter or followed by a 
    /// lowercase letter (but not for the first char in string). 
    /// This keeps groups of uppercase letters - e.g. acronyms - together.
    /// </summary>
    /// <param name="pascalCaseString">A string in PascalCase</param>
    /// <returns></returns>
    public static string Wordify(string pascalCaseString)
    {            
        Regex r = new Regex("(?<=[a-z])(?<x>[A-Z])|(?<=.)(?<x>[A-Z])(?=[a-z])");
        return r.Replace(pascalCaseString, " ${x}");
    }

(需要,'使用 System.Text.RegularExpressions;')

因此:

Console.WriteLine(Wordify(ThisIsValueA.ToString()));

会回来,

"This Is Value A".

它比提供描述属性更简单,也更少冗余。

仅当您需要提供间接层(问题没有要求)时,属性才在这里有用。

于 2008-08-17T13:10:20.513 回答
12

Enums 上的 .ToString 在 C# 中相对较慢,与 GetType().Name 相当(它甚至可能在幕后使用它)。

如果您的解决方案需要非常快速或高效,您最好将转换缓存在静态字典中,然后从那里查找它们。


@Leon 的代码的一个小改编以利用 C#3。作为枚举的扩展,这确实是有意义的——如果您不想把所有枚举都弄乱,您可以将其限制为特定类型。

public static string Wordify(this Enum input)
{            
    Regex r = new Regex("(?<=[a-z])(?<x>[A-Z])|(?<=.)(?<x>[A-Z])(?=[a-z])");
    return r.Replace( input.ToString() , " ${x}");
}

//then your calling syntax is down to:
MyEnum.ThisIsA.Wordify();
于 2008-08-17T16:05:16.417 回答
5

我见过的大多数示例都涉及使用 [Description] 属性标记您的枚举值,并使用反射在值和描述之间进行“转换”。这是一篇关于它的旧博客文章:

http://geekswithblogs.net/rakker/archive/2006/05/19/78952.aspx

于 2008-08-17T12:28:36.230 回答
4

您可以从 System.Reflection 的“属性”类继承来创建自己的“描述”类。像这样(从这里):

using System;
using System.Reflection;
namespace FunWithEnum
{
    enum Coolness : byte
    {
        [Description("Not so cool")]
        NotSoCool = 5,
        Cool, // since description same as ToString no attr are used
        [Description("Very cool")]
        VeryCool = NotSoCool + 7,
        [Description("Super cool")]
        SuperCool
    }
    class Description : Attribute
    {
        public string Text;
        public Description(string text)
        {
            Text = text;
        }
    }
    class Program
    {
        static string GetDescription(Enum en)
        {
            Type type = en.GetType();
            MemberInfo[] memInfo = type.GetMember(en.ToString());
            if (memInfo != null && memInfo.Length > 0)
            {
                object[] attrs = memInfo[0].GetCustomAttributes(typeof(Description), false);
                if (attrs != null && attrs.Length > 0)
                    return ((Description)attrs[0]).Text;
            }
            return en.ToString();
        }
        static void Main(string[] args)
        {
            Coolness coolType1 = Coolness.Cool;
            Coolness coolType2 = Coolness.NotSoCool;
            Console.WriteLine(GetDescription(coolType1));
            Console.WriteLine(GetDescription(coolType2));
        }
    }
}
于 2008-08-17T13:01:02.030 回答
2

你也可以看看这篇文章: http: //www.codeproject.com/KB/cs/enumdatabinding.aspx

它专门关于数据绑定,但展示了如何使用属性来装饰枚举值并提供“GetDescription”方法来检索属性的文本。使用内置描述属性的问题在于该属性还有其他用途/用户,因此描述有可能出现在您不希望出现的位置。自定义属性解决了这个问题。

于 2008-08-17T13:00:10.487 回答
0

我发现最好用低于分数来定义你的枚举值,所以 ThisIsValueA 将是 This_Is_Value_A 然后你可以做一个 enumValue.toString().Replace("_"," ") 其中 enumValue 是你的变量。

于 2008-08-17T13:57:07.190 回答
0

向每个枚举添加属性的另一种Description方法是创建扩展方法。要重用 Adam 的“Coolness”枚举:

public enum Coolness
{
    NotSoCool,
    Cool,
    VeryCool,
    SuperCool
}

public static class CoolnessExtensions
{
    public static string ToString(this Coolness coolness)
    {
        switch (coolness)
        {
            case Coolness.NotSoCool:
                return "Not so cool";
            case Coolness.Cool:
                return "Cool";
            case Coolness.VeryCool:
                return "Very cool";
            case Coolness.SuperCool:
                return Properties.Settings.Default["SuperCoolDescription"].ToString();
            default:
                throw new ArgumentException("Unknown amount of coolness", nameof(coolness));
        }
    }
}

虽然这意味着描述离实际值更远,但它允许您使用本地化来为每种语言打印不同的字符串,例如在我的VeryCool示例中。

于 2018-08-28T23:58:04.810 回答
0
Enum.GetName(typeof(EnumFoo), EnumFoo.BarValue)
于 2021-08-19T13:54:27.230 回答