我知道下面是不可能的,因为枚举的类型必须是int

enum GroupTypes
{
    TheGroup = "OEM",
    TheOtherGroup = "CMB"
}

从我的数据库中,我得到了一个不全面的代码字段(OEM和CMBs)。我想让这个字段成为一个枚举或其他可以理解的东西。因为如果目标是可读性,解决方案就应该简洁。

我还有其他选择吗?


当前回答

我想完全避免使用字符串字面量,而且我也不需要在项目描述中有空间。更重要的是,我想要有一种机制来检查所提供的字符串是否是一个有效的项目,所以我想出了这个解决方案:

public class Seasons
{
    public static string Spring { get; }
    public static string Summer { get; }
    public static string Fall { get; }
    public static string Winter { get; }

    public static bool IsValid(string propertyName)
    {
        if (string.IsNullOrEmpty(propertyName))
        {
            return false;
        }

        try
        {           
            return typeof(Seasons).GetProperty(propertyName) != null;
        }
        catch
        {
            return false;
        }       
    }
}

它是这样工作的:

void Main()
{
    string s = nameof(Seasons.Fall);
    Console.WriteLine($"Fall is valid: {Seasons.IsValid(s)}"); // true

    s = "WrongSeason";
    Console.WriteLine($"WrongSeason is valid: {Seasons.IsValid(s)}"); // false
}

我尝试将IsValid()重构为基类并使用反射来读取类型(MethodBase.GetCurrentMethod(). declaringtype),但由于我希望它是静态的,所以它返回基类类型,而不是继承的类型。你的补救措施将是非常欢迎的!这就是我想要达到的目标:

public  class Seasons : ConstantStringsBase
{
    // ... same
}

public  class ConstantStringsBase
{
    public static bool IsValid(string propertyName)
    {       
        return MethodBase.GetCurrentMethod().DeclaringType.GetProperty(propertyName) != null;
    }
}

其他回答

我做过类似的事情;

public enum BusinessUnits
{
    NEW_EQUIPMENT = 0,
    USED_EQUIPMENT = 1,
    RENTAL_EQUIPMENT = 2,
    PARTS = 3,
    SERVICE = 4,
    OPERATOR_TRAINING = 5
}

public class BusinessUnitService
{
    public static string StringBusinessUnits(BusinessUnits BU)
    {
        switch (BU)
        {
            case BusinessUnits.NEW_EQUIPMENT: return "NEW EQUIPMENT";
            case BusinessUnits.USED_EQUIPMENT: return "USED EQUIPMENT";
            case BusinessUnits.RENTAL_EQUIPMENT: return "RENTAL EQUIPMENT";
            case BusinessUnits.PARTS: return "PARTS";
            case BusinessUnits.SERVICE: return "SERVICE";
            case BusinessUnits.OPERATOR_TRAINING: return "OPERATOR TRAINING";
            default: return String.Empty;
        }
    }
}

用这个称呼它;

BusinessUnitService.StringBusinessUnits(BusinessUnits.PARTS)

如果我理解正确,你需要一个从字符串到enum的转换:

enum GroupTypes {
    Unknown = 0,
    OEM = 1,
    CMB = 2
}
static GroupTypes StrToEnum(string str){
    GroupTypes g = GroupTypes.Unknown;
    try {
        object o = Enum.Parse(typeof(GroupTypes), str, true);
        g = (GroupTypes)(o ?? 0);
    } catch {
    }
    return g;
}
// then use it like this
GroupTypes g1 = StrToEnum("OEM");
GroupTypes g2 = StrToEnum("bad value");

如果您愿意,可以使用枚举类型的泛型使其更加花哨。

下面是我对这个问题的看法,使用c# 9.0语法来保持整洁。我为枚举定义了一个基类:

public class StringEnum
{
    protected StringEnum(string value) { Value = value; }
    public string Value { get; }
    public override string ToString() => Value;
}

创建新的枚举样式类型是简单而紧凑的:

public class GroupTypes : StringEnum
{ 
    private GroupTypes(string value) : base(value) {}

    public static readonly GroupTypes TheGroup = new("OEM");
    public static readonly GroupTypes TheOtherGroup = new("CMB");
}

像这样使用它:

void Example(GroupTypes groupType)
{
    Console.WriteLine(groupType); // Will print "OEM" or "CMB"
    if (groupType == GroupTypes.TheGroup) { ... }
}

你也可以给StringEnum添加更多的功能,这样你的所有子类都可以使用(例如,实现IComparable和重写Equals和GetHashCode)

这里是扩展方法,我用来获得枚举值作为字符串。首先是枚举。

public enum DatabaseEnvironment
{
    [Description("AzamSharpBlogDevDatabase")]
    Development = 1, 
    [Description("AzamSharpBlogQADatabase")]
    QualityAssurance = 2, 
    [Description("AzamSharpBlogTestDatabase")] 
    Test = 3
}

Description属性来自System.ComponentModel。

这是我的扩展方法:

public static string GetValueAsString(this DatabaseEnvironment environment) 
{
    // get the field 
    var field = environment.GetType().GetField(environment.ToString());
    var customAttributes = field.GetCustomAttributes(typeof (DescriptionAttribute), false);

    if(customAttributes.Length > 0)
    {
        return (customAttributes[0] as DescriptionAttribute).Description;  
    }
    else
    {
        return environment.ToString(); 
    }
}

现在,你可以使用下面的代码访问枚举字符串值:

[TestFixture]
public class when_getting_value_of_enum
{
    [Test]
    public void should_get_the_value_as_string()
    {
        Assert.AreEqual("AzamSharpBlogTestDatabase",DatabaseEnvironment.Test.GetValueAsString());  
    }
}

Glennular Extension方法的一个小调整,所以你可以在其他东西上使用扩展,而不仅仅是ENUM的;

using System;
using System.ComponentModel;
namespace Extensions {
    public static class T_Extensions {
        /// <summary>
        /// Gets the Description Attribute Value
        /// </summary>
        /// <typeparam name="T">Entity Type</typeparam>
        /// <param name="val">Variable</param>
        /// <returns>The value of the Description Attribute or an Empty String</returns>
        public static string Description<T>(this T t) {
            DescriptionAttribute[] attributes = (DescriptionAttribute[])t.GetType().GetField(t.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
            return attributes.Length > 0 ? attributes[0].Description : string.Empty;
        }
    }
}

或者使用Linq

using System;
using System.ComponentModel;
using System.Linq;

namespace Extensions {


public static class T_Extensions {
        public static string Description<T>(this T t) =>
            ((DescriptionAttribute[])t
            ?.GetType()
            ?.GetField(t?.ToString())
            ?.GetCustomAttributes(typeof(DescriptionAttribute), false))
            ?.Select(a => a?.Description)
            ?.FirstOrDefault() 
            ?? string.Empty;  
    }
}