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

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

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

我还有其他选择吗?


当前回答

下面是我对这个问题的看法,使用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)

其他回答

下面是我对这个问题的看法,使用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 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)

基于https://stackoverflow.com/a/1343517/1818723,我提出了一个枚举与TryParse方法

public class FancyStringEnum
{
    private FancyStringEnum(string value) { Value = value; }

    public string Value { get; private set; }

    private static List<FancyStringEnum> choices = new List<FancyStringEnum>
    {
        new FancyStringEnum("Small") ,
        new FancyStringEnum("Big Thing") ,
        new FancyStringEnum("Value with Spaces")
    };

    public static FancyStringEnum Small { get { return choices[0]; } }
    public static FancyStringEnum BigThing { get { return choices[1]; } }
    public static FancyStringEnum ValueWithSpaces { get { return choices[2]; } }

    public override string ToString()
    {
        return Value;
    }

    public static bool TryParse(string value, bool ignoreCase, out FancyStringEnum result)
    {
        var sc = StringComparison.InvariantCulture;
        if (ignoreCase)
            sc = StringComparison.InvariantCultureIgnoreCase;

        foreach (var choice in choices)
        {

            if (choice.Value.Equals(value, sc))
            {
                result = choice;
                return true;
            }
        }

        result = new FancyStringEnum(null);
        return false;
    }

    public static FancyStringEnum Parse(string value, bool ignoreCase)
    {
        var sc = StringComparison.InvariantCulture;
        if (ignoreCase)
            sc = StringComparison.InvariantCultureIgnoreCase;

        foreach (var choice in choices)
        {

            if (choice.Value.Equals(value, sc))
            {
                return choice;
            }
        }

        return new FancyStringEnum(null);
    }
}

传入类型安全的字符串值作为参数:

public static void Do(string message, FancyStringEnum value)
{
    if (value == FancyStringEnum.Small)
    {
        //do something
    } else if (value == FancyStringEnum.BigThing)
    {
        //do something else
    }
}

TryParse和Parse在行动:

string something = "something"; //substiture with "small" to see it parsed 
if (FancyStringEnum.TryParse(something, true, out var se))
    Console.WriteLine(se.Value);
else
    Console.WriteLine($"unable to parse {something}");

//or    

var v2 = FancyStringEnum.Parse(something, true);
if (v2.Value == null)
    Console.WriteLine($"unable to parse {something}");
else
    Console.WriteLine(v2.Value); //do something with parsed enum

    

是否可以提取基类,用更少的代码创建StringEnums

尝试向静态类中添加常量。你最终不会得到一个Type,但你会得到可读的、有组织的常量:

public static class GroupTypes {

    public const string TheGroup = "OEM";
    public const string TheOtherGroup = "CMB";

}

根据其他人的意见,这是我想到的。这种方法避免了在想要获得常量值的地方键入. value。

我有一个基类的所有字符串枚举像这样:

using System;
using Newtonsoft.Json;

[JsonConverter(typeof(ConstantConverter))]
public class StringEnum: IConvertible
{
    public string Value { get; set; }

    protected StringEnum(string value)
    {
        Value = value;
    }

    public static implicit operator string(StringEnum c)
    {
        return c.Value;
    }
    public string ToString(IFormatProvider provider)
    {
        return Value;
    }

    public TypeCode GetTypeCode()
    {
        throw new NotImplementedException();
    }

    public bool ToBoolean(IFormatProvider provider)
    {
        throw new NotImplementedException();
    }
    //The same for all the rest of IConvertible methods
}

JsonConverter是这样的:

using System;
using Newtonsoft.Json;

class ConstantConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (value == null)
        {
            serializer.Serialize(writer, null);
        }
        else
        {
            serializer.Serialize(writer, value.ToString());
        }
    }
}

一个实际的string enum是这样的:

public sealed class Colors : StringEnum
{
    public static Colors Red { get { return new Catalog("Red"); } }
    public static Colors Yellow { get { return new Catalog("Yellow"); } }
    public static Colors White { get { return new Catalog("White"); } }

    private Colors(string value) : base(value) { }
}

有了这个,你可以使用颜色。红色甚至序列化到json而不使用Value属性