枚举类型的ToString方法返回值可以被保证吗?

9
我现在处理的数据库中有一个varchar字段,我希望在我的代码中将可能的值映射到一个枚举类型,例如:
public enum UserStatus
{
    Anonymous,
    Enrolled,
    SuperUser
}

在此列的数据库级别上,存在一个限制条件,该值必须为:

ANONYMOUS
ENROLLED
SUPERUSER

我能做到吗:

UserStatus.SuperUser.ToString()

并且让该值成为超级用户,保持一致性并避免未来出现问题?

1
如果您掌控代码库,那么您肯定可以确保这一点。 - David Heffernan
1
ToUpperInvariant() 是一个 C# 中的字符串方法,可以将字符串转换为大写字母形式而且不受区域性影响。 - PoByBolek
1
你甚至可能不需要这个。你没有指定你的SQL方言,但其中许多对于文本默认是不区分大小写的,这意味着'SuperUser'将满足约束条件。 - user743382
3个回答

7

更好的解决方案可能是利用DescriptionAttribute

public enum UserStatus
{
    [Description("ANONYMOUS")]
    Anonymous,
    [Description("ENROLLED")]
    Enrolled,
    [Description("SUPERUSER")]
    SuperUser
}

然后使用类似以下的内容:

/// <summary>
/// Class EnumExtenions
/// </summary>
public static class EnumExtenions
{
    /// <summary>
    /// Gets the description.
    /// </summary>
    /// <param name="e">The e.</param>
    /// <returns>String.</returns>
    public static String GetDescription(this Enum e)
    {
        String enumAsString = e.ToString();
        Type type = e.GetType();
        MemberInfo[] members = type.GetMember(enumAsString);
        if (members != null && members.Length > 0)
        {
            Object[] attributes = members[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
            if (attributes != null && attributes.Length > 0)
            {
                enumAsString = ((DescriptionAttribute)attributes[0]).Description;
            }
        }
        return enumAsString;
    }

    /// <summary>
    /// Gets an enum from its description.
    /// </summary>
    /// <typeparam name="TEnum">The type of the T enum.</typeparam>
    /// <param name="description">The description.</param>
    /// <returns>Matching enum value.</returns>
    /// <exception cref="System.InvalidOperationException"></exception>
    public static TEnum GetFromDescription<TEnum>(String description)
        where TEnum : struct, IConvertible // https://dev59.com/53VD5IYBdhLWcg3wHn2d#79903
    {
        if (!typeof(TEnum).IsEnum)
        {
            throw new InvalidOperationException();
        }
        foreach (FieldInfo field in typeof(TEnum).GetFields())
        {
            DescriptionAttribute attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
            if (attribute != null)
            {
                if (attribute.Description == description)
                {
                    return (TEnum)field.GetValue(null);
                }
            }
            else
            {
                if (field.Name == description)
                {
                    return (TEnum)field.GetValue(null);
                }
            }
        }
        return default(TEnum);
    }
}

现在你正在引用UserStatus.Anonymous.GetDescription()

当然,你也可以创建自己的DatabaseMapAttribute(或其他类似的东西),并创建自己的扩展方法。然后,你就可以完全摆脱对System.ComponentModel的引用了。这完全由你决定。


@hvd: 呼叫不错。仍在度过一个星期一。;-) - Brad Christie
2
这真的更好吗?从你必须要维护的代码量来看,我更喜欢Habib的解决方案... - PoByBolek
1
@PoByBolek的一个主要优点是,它支持不符合C#标识符要求的字符串。 - user743382
@PoByBolek 你不必真的维护它,因为它是相当琐碎的代码,更多是由于通用部分。 - Silvermind
1
еҪ“然еҸҜд»Ҙ...дҪҶжҳҜOPзҡ„йҷҗеҲ¶жҳҜиҜҘеҖјеҝ…йЎ»жҳҜANONYMOUSгҖҒENROLLEDжҲ–SUPERUSERд№ӢдёҖгҖӮеҸӘжҳҜиҝҷд№ҲиҜҙиҖҢе·І... ;) - PoByBolek
显示剩余3条评论

6

你不能为枚举类型重写ToString方法,但可以创建自己的扩展方法,例如:

public static class MyExtensions
{
    public static string ToUpperString(this UserStatus userStatus)
    {
        return userStatus.ToString().ToUpper();// OR .ToUpperInvariant 
    }
}

然后像这样调用:

string str = UserStatus.Anonymous.ToUpperString();

@user1361315,这是用于无文化差异的转换为大写字母。请参阅此链接 - Habib
我不关心文化,因为它只是用于数据库,所以无论如何文化都不应该改变。那么使用ToUpperInvariant可以吗? - loyalflow
@user1361315,如果文化不是问题的话,您可以使用 ToUpper - Habib

1

Enum.ToString支持4种不同的格式。我会选择:

UserStatus.SuperUser.ToString("G").ToUpper();

"

“G” 确保它首先尝试获取枚举的字符串表示。

"

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