C#中的枚举类型开关

6

我有一个枚举:

public enum Status 
{ 
    Incomplete = 1, Complete = 2, Cancelled = 3, Deleted = 4 
}

现在我想在某个页面上列出这个枚举类型的复选框列表。但是,我希望每个复选框的文本显示的不是枚举类型中的文本。
即复选框应该显示:
- "未处理" 而不是 "Incomplete" - "已处理" 而不是 "Complete" - "作废" 而不是 "Cancelled"
是否可以使用foreach循环遍历此枚举类型,并根据状态更新文本内容呢?像这样:
var statuses = Enum.GetNames(typeof(Status));
foreach (var status in statuses)))
{
    switch (status)
    {
        case Status.Complete.ToString(): 
        status = "Processed";
        break; ...etc                 
    }
}

任何想法都将不胜感激。
3个回答

14

C#有一种语言特性可以直接解决你的问题。这里是一篇文章,提供了完整细节:这里

简而言之:对每个值应用扩展属性值:

enum OrderStatus  
{  
    [EnumValueData(Name="New Order")]  
    NewOrder = 1,  
    [EnumValueData(Name="In Process")]  
    Processing = 2,  
    [EnumValueData(Name="Shipped")]  
    Shipped = 3  
}  

然后将这些值应用到你的单选按钮、列表框或其他控件中:

public static Dictionary<int, string> GetListItems(Type enumType)  
{  
    if (!enumType.IsEnum)  
        throw new ApplicationException("GetListItems does not support non-enum types");  
    Dictionary<int, string> list = new Dictionary<int, string>();  
    foreach(FieldInfo field in enumType.GetFields(BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public))  
    {  
        int value;  
        string display;  
        value = (int)field.GetValue(null);  
        display = Enum.GetName(enumType, value);  
        foreach(Attribute currAttr in field.GetCustomAttributes(true))  
        {  
            EnumValueDataAttribute valueAttribute = currAttr as EnumValueDataAttribute;  
            if (valueAttribute != null)  
                display = valueAttribute.Name;  
        }  
        list.Add(value, display);  
    }  
    return list;  
}  

10
在我看来,这段代码创建了一个新的属性(EnumValueDataAttribute),但其实已经存在一个类似的属性(System.ComponentModel.DescriptionAttribute)。虽然这段代码可以工作,但我想知道为什么要创建一个新的属性而不使用DescriptionAttribute呢? - TLiebe
@TLiebe - 很好的观点。我是多年人工强制编码标准的受害者。这是我加入的开发人员一直在做的方式。我不会打破模式; 这会导致糟糕的代码审查! :) - Bob Kaufman

10
你可以在System.ComponentModel类中使用Description属性为每个枚举值分配文本描述。然后,您可以通过迭代枚举并获取每个的Description属性来设置文本属性,而不是使用switch语句。
public enum Status
{
    [Description("Not Processed")] Incomplete = 1,
    [Description("Processed")] Complete = 2,
    [Description("Void")] Cancelled = 3,
    Deleted = 4
}

您可以使用以下内容来获取单个枚举值的描述(或修改它以返回像Bob在示例中展示的Dictionary):
    public static string GetEnumDescription ( Object value )
    {
        try
        {
            Type objType = value.GetType();
            FieldInfo fldInf = objType.GetField( Enum.GetName( objType, value ) );

            Object[ ] attributes = fldInf.GetCustomAttributes( false );

            if ( attributes.Length > 0 )
            {
                DescriptionAttribute descAttr = ( DescriptionAttribute )attributes[ 0 ];
                return descAttr.Description;
            }
            else
            {
                return value.ToString();
            }
        }
        catch
        {
            return string.Empty;
        }
    }

1
我可以挑毛病吗?只是想指出,在“真正”的代码中,你可能需要比attributes[0]更强大的东西。另外,我相当确定try/catch是纯邪恶的,但这个主题上有其他的讨论。 </ 挑毛病>我将来会尝试这个解决方案。谢谢分享! - jyoungdev
欢迎进行建设性的吹毛求疵。你提出的观点很好,虽然我承认这段代码是我自己写的,但我会用(诚实地说很差的)借口为自己辩护,即它是旧的,来自我编写的最初的一些.NET代码。 - TLiebe

0
你可以将你的修改字符串放入一个数组中,然后使用枚举索引来访问数组元素。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接