C# 数字枚举值作为字符串

Posted

技术标签:

【中文标题】C# 数字枚举值作为字符串【英文标题】:C# numeric enum value as string 【发布时间】:2011-03-27 13:26:13 【问题描述】:

我有以下枚举:

public enum Urgency 
    VeryHigh = 1,
    High     = 2,
    Routine  = 4

我可以像这样获取 枚举“值”作为字符串

((int)Urgency.Routine).ToString() // returns "4"  

注意:这不同于:

Urgency.Routine.ToString() // returns "Routine"
(int)Urgency.Routine       // returns 4

有没有一种方法可以创建扩展类或静态实用程序类,以提供一些语法糖? :)

【问题讨论】:

您能更准确地了解您要查找的内容吗? 即enumValue.ToValueString() == int 值? 底层 int 值 - 但作为字符串(而不是作为字符串的枚举)而不是记住转换为 int 然后转换为字符串的古老语法,而是一个静态类,其方法采用any 枚举值会使其更易于使用。我怀疑该语言可能不支持我所追求的。 .. 认为我做了你想要的。 【参考方案1】:

一个简单的方法

((Urgency)4).ToString() // returns "Routine"

【讨论】:

【参考方案2】:

很棒的东西...我现在为我的项目添加了一个扩展方法

public static class EnumExtensions 
 
    public static string NumberString(this Enum enVal) 
     
        return enVal.ToString("D"); 
    
 

现在我可以通过调用 Urgency.Routine.NumberString(); 来获取 int 值 - 作为字符串 - 感谢 Frankentosh 和 Jon :)

【讨论】:

【参考方案3】:

为了获得更多“人类可读”的枚举描述(例如,您的示例中的“非常高”而不是“非常高”),我使用如下属性修饰了枚举值:

public enum MeasurementType

    Each,

    [DisplayText("Lineal Metres")]
    LinealMetre,

    [DisplayText("Square Metres")]
    SquareMetre,

    [DisplayText("Cubic Metres")]
    CubicMetre,

    [DisplayText("Per 1000")]
    Per1000,

    Other



public class DisplayText : Attribute


    public DisplayText(string Text)
    
        this.text = Text;
    


    private string text;


    public string Text
    
        get  return text; 
        set  text = value; 
    

然后,使用这样的扩展方法:

    public static string ToDescription(this Enum en)
    

        Type type = en.GetType();

        MemberInfo[] memInfo = type.GetMember(en.ToString());

        if (memInfo != null && memInfo.Length > 0)
        

            object[] attrs = memInfo[0].GetCustomAttributes(
                                          typeof(DisplayText),

                                          false);

            if (attrs != null && attrs.Length > 0)

                return ((DisplayText)attrs[0]).Text;

        

        return en.ToString();

    

然后你就可以打电话了

myEnum.ToDescription()
以将您的枚举显示为更具可读性的文本。

【讨论】:

我也做过类似的事情,但通常只是依赖于骆驼套管的约定。虽然没有按照问题的要求做。 谢谢 - 但不返回 int 值 - 作为字符串 :) 您没有添加DisplayText 属性的声明。可以加一下吗? 谢谢斯图尔特。它现在正在工作。不幸的是,我不能给你多个 +1,所以我想我之前的一个就足够了。 我认为这可能是一位前同事这样做,因为我多次使用相同的解决方案,甚至调用属性 DisplayText - 尽管我也玩过进一步的装饰枚举所以我通过“GetAttrib()”函数走很长一段路 - 返回 (TAttrib)enumValue.GetType().GetMember(enumValue.ToString()).First().GetCustomAttributes(typeof(TAttrib), false) .FirstOrDefault();【参考方案4】:

如果您愿意,可以使扩展方法适用于所有枚举:

public static string ToValueString(this Enum enumValue) 

    if (enumValue.GetType().GetEnumUnderlyingType() == typeof(int))
        return ((int)(object)enumValue).ToString();
    else if (enumValue.GetType().GetEnumUnderlyingType() == typeof(byte))
        return ((byte)(object)enumValue).ToString();
    ... 
        

【讨论】:

+1:有趣……但同时看到双重演员有点不寻常。好把戏。 :) 可以使用Enum 而不是T where T : struct 你是对的。不知道为什么我认为这在这种情况下很有帮助。更改它以反映您的建议。【参考方案5】:

如果您只想处理这个枚举,请使用 Mark Byer 的解决方案。

对于更通用的解决方案:

public static string NumberString(this Enum enVal) 

    return Convert.ToDecimal(enVal).ToString("0");

转换为十进制意味着您不需要显式处理 8 种不同的允许的基础整数类型,因为它们都无损地转换为十进制,但彼此之间不转换(ulong 和 long 不会在彼此之间进行无损转换,而是两者都可以处理所有其余的)。这样做可能会更快(尤其是如果您在比较顺序中选择得很好),但会更加冗长,收获相对较小。

编辑:

虽然上面的不如弗兰肯托什,但弗兰肯托什看穿了真正的问题,并且非常雄辩地解决了它。

【讨论】:

【参考方案6】:

您应该能够使用 Enums ToString 方法的重载来给它一个格式字符串,这会将枚举的值打印为字符串。

public static class Program

    static void Main(string[] args)
    
        var val = Urgency.High;
        Console.WriteLine(val.ToString("D")); 
    


public enum Urgency 
 
    VeryHigh = 1,
    High = 2,
    Low = 4

【讨论】:

波什。美丽的简单。让我想删除我的答案! +1 是的,在提供相同的结果和不同的查询方法时,横向思考很好。代码public static string NumberString(this Enum enVal)return enVal.ToString("D"); 应该是您的想法并将其转化为所要求的扩展方法。 好东西......请参阅下面的答案 我喜欢这个而不是另一个使用扩展方法的。通过创建扩展方法,您只需为代码添加不必要的依赖项。记住你的代码越少依赖越好!! 应用于多个枚举值(示例):new[] ProductStatus.Open, ProductStatus.Deprecated .Select(s => s.ToString("D"))【参考方案7】:

稍微反思一下怎么样?应该适用于所有底层类型。

public static class EnumTools

    public static string ToRawValueString(this Enum e)
    
        return e
            .GetType()
            .GetFields(BindingFlags.Public | BindingFlags.Static)
            .First(f => f.Name==e.ToString())
            .GetRawConstantValue()
            .ToString();
    

然后:

Console.WriteLine(Urgency.High.ToRawValueString()); //Writes "2"

【讨论】:

First() 如果在枚举中没有定义的值匹配该值,则将失败,特别常见于标志枚举并且在其他情况下可能(只要Enum.IsDefined(e.GetType(), e)返回false)这需要为了在这种情况下更具防御性,然后回退到不会在有效(如果尴尬)值上失败将是使用非反射方法,当您重构时意味着您将删除反射位除非它被证明要快得多。 @Jon :我看不出 Enum 的类型怎么可能不包含它的条目。我错过了什么?编辑:明白了,枚举可能是 ORed 标志。我同意你的评论。 这是最常见的情况。将基础类型的任何值强制转换为枚举类型也是有效的,因此存在 Enum.IsDefined() 以允许捕获可能是方法的无效参数或属性的无效值的情况。【参考方案8】:

您可以为您的特定类型编写扩展方法:

public static class UrgencyExtension

    public static string ToIntegerString(this Urgency u)
    
        return ((int)u).ToString();
    

如下使用:

Urgency u = Urgency.Routine;
string s = u.ToIntegerString();

【讨论】:

以上是关于C# 数字枚举值作为字符串的主要内容,如果未能解决你的问题,请参考以下文章

C# Enum,Int,String的互相转换 枚举转换

C# 根据数字值获取相应枚举

枚举值返回为数字 [重复]

将 Typescript 枚举从字符串转换为数字(角度)[重复]

枚举返回 int 而不是字符串 C#

将枚举值作为参数的通用 C# 方法[重复]