HOWTO · Csharp

在 C# 中将枚举转换为字符串

在 C# 中将枚举值转换为字符串时,可直接用 `ToString()` 获取成员名称;若需要自定义标签,可用 `DescriptionAttribute` 或 `switch` 语句映射。

本页内容

枚举值可以通过几种方式转换为字符串,具体取决于你需要的是已声明的成员名称,还是供人阅读的独立标签。成员名称可直接使用 ToString()。如果标签应放在枚举声明旁边,可使用 DescriptionAttribute;如果希望映射关系清晰明确,则可使用 switch 语句。下面的示例会展示各种方式的取舍,以及值没有自定义标签时会发生什么。(C#)

使用 ToString() 将枚举值转换为字符串

对枚举调用 ToString() 会返回其已声明成员的名称。这适用于日志、诊断信息,以及将 InProgress 这类名称直接显示出来也合适的界面。它不会添加空格,也不会改变大小写。Console.WriteLine 也会将枚举值转换为名称;不过,当你要把转换结果赋给字符串变量时,显式调用 ToString() 能更清楚地表明转换意图。

运行以下示例:

本节中的代码以及显示的标签或输出仍为英文。

using System;

enum Status { InProgress, Completed }

class Program
{
    static void Main()
    {
        Status status = Status.Completed;
        string name = status.ToString();
        Console.WriteLine(name);
    }
}

对于这个已声明的值,程序会输出 Completed。如果某个数值没有对应的已声明成员,它会以数字形式表示。对于标志枚举,ToString() 可能会将匹配的标志名称连接起来显示,但不会为组合值生成自定义短语。

使用 DescriptionAttribute 添加便于阅读的标签

如果标签需要与标识符不同,可以为每个成员添加 DescriptionAttribute。通过反射,可以找到命名值对应的字段并读取其描述。下面的辅助方法在没有描述时会回退到成员名称;如果该值没有匹配的已声明字段,则会回退到数值表示。

本节中的代码以及显示的标签或输出仍为英文。

using System;
using System.ComponentModel;
using System.Reflection;

enum Status
{
    [Description("In progress")]
    InProgress,
    [Description("Successfully completed")]
    Completed
}

static class EnumLabels
{
    public static string GetLabel(Status value)
    {
        string name = Enum.GetName(typeof(Status), value);
        if (name == null)
            return value.ToString();

        FieldInfo field = typeof(Status).GetField(name);
        DescriptionAttribute attribute = (DescriptionAttribute)Attribute.GetCustomAttribute(
            field, typeof(DescriptionAttribute));
        return attribute == null ? name : attribute.Description;
    }
}

class Program
{
    static void Main()
    {
        Console.WriteLine(EnumLabels.GetLabel(Status.Completed));
    }
}

这种做法能让标签与枚举成员放在一起,但读取标签需要使用反射,而且必须明确选择回退行为。在这个示例中,未命名的数值无法附加属性,因此辅助方法会返回该数值对应的字符串。如果标签经常变化或需要本地化,应将映射放在合适的应用层,而不要把属性当作本地化系统。

使用 switch 语句将枚举值映射为字符串

switch 语句能在同一处清楚列出每个受支持的标签和回退行为。对于规模较小且稳定的映射,或者希望显示文本与枚举声明分开管理的情况,这种方式很合适。添加枚举成员时,也要为它添加一个 case;下面的回退分支会对任何未列出的值返回枚举的默认字符串表示。

本节中的代码以及显示的标签或输出仍为英文。

using System;

enum Status { InProgress, Completed }

static class EnumLabels
{
    public static string GetLabel(Status value)
    {
        switch (value)
        {
            case Status.InProgress:
                return "In progress";
            case Status.Completed:
                return "Successfully completed";
            default:
                return value.ToString();
        }
    }
}

class Program
{
    static void Main()
    {
        Console.WriteLine(EnumLabels.GetLabel(Status.Completed));
    }
}

明确设置回退行为很重要,因为枚举变量可以保存并非已声明成员的数值。对于标志枚举,组合值可能与任何单个 case 都不匹配;除非为组合值添加专门逻辑,否则此映射会返回枚举的默认表示。

选择合适的方法并处理边缘情况

如果枚举成员名称已经可以直接使用,就选择 ToString()。如果每个成员都应有稳定的显示标签,并且适合使用小型反射辅助方法,就选择 DescriptionAttribute。如果希望在常规代码中明确控制标签和回退行为,就选择 switch 映射。属性示例和 switch 示例使用了不同于枚举标识符的标签,但两者都不会改变枚举值本身。

对于这两种自定义标签方案,都要考虑与已声明成员不匹配的值,以及标志组合值。请决定这些情况应显示数值或枚举的默认字符串、使用通用标签,还是交由专门逻辑处理,并确保在所有显示该值的地方采用一致的处理方式。这些方案处理的是显示文本;序列化和数据库表示有各自的约定,应单独配置。