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

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

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

我还有其他选择吗?


当前回答

根据其他人的意见,这是我想到的。这种方法避免了在想要获得常量值的地方键入. 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属性

其他回答

我的第一个问题-你有访问数据库本身的权限吗?这应该在数据库中规范化,否则,任何解决方案都将容易出错。根据我的经验,充满“OEM”和“CMB”的数据字段往往会随着时间的推移混合“OEM”和其他“垃圾数据”....如果可以规范化它,就可以使用包含元素的表中的键作为Enum,这样就完成了,结构更加简洁。

如果这是不可用的,我将使你的Enum,并使一个类来解析你的字符串为你的Enum。这至少会让您在处理非标准条目时具有一定的灵活性,在捕获或处理错误时也比使用enumeration . parse /Reflection/etc等方法灵活得多。字典可以工作,但如果你遇到大小写问题,可能会崩溃。

我建议你写一个类,这样你就可以:

// I renamed this to GroupType, since it sounds like each element has a single type...
GroupType theType = GroupTypeParser.GetGroupType(theDBString);

这样可以保留大部分的可读性,而不必更改DB。

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

使用类。

编辑:更好的例子

class StarshipType
{
    private string _Name;
    private static List<StarshipType> _StarshipTypes = new List<StarshipType>();

    public static readonly StarshipType Ultralight = new StarshipType("Ultralight");
    public static readonly StarshipType Light = new StarshipType("Light");
    public static readonly StarshipType Mediumweight = new StarshipType("Mediumweight");
    public static readonly StarshipType Heavy = new StarshipType("Heavy");
    public static readonly StarshipType Superheavy = new StarshipType("Superheavy");

    public string Name
    {
        get { return _Name; }
        private set { _Name = value; }
    }

    public static IList<StarshipType> StarshipTypes
    {
        get { return _StarshipTypes; }
    }

    private StarshipType(string name, int systemRatio)
    {
        Name = name;
        _StarshipTypes.Add(this);
    }

    public static StarshipType Parse(string toParse)
    {
        foreach (StarshipType s in StarshipTypes)
        {
            if (toParse == s.Name)
                return s;
        }
        throw new FormatException("Could not parse string.");
    }
}

您是否考虑过使用字典查找表?

enum GroupTypes
{
    TheGroup,
    TheOtherGroup
}

Dictionary<string, GroupTypes> GroupTypeLookup = new Dictionary<string, GroupTypes>();
// initialize lookup table:
GroupTypeLookup.Add("OEM", TheGroup);
GroupTypeLookup.Add("CMB", TheOtherGroup);

然后,您可以使用GroupTypeLookup.TryGetValue()在读取字符串时查找它。

为你的DB创建第二个枚举,包含以下内容:

enum DBGroupTypes
{
    OEM = 0,
    CMB = 1
}

现在,您可以使用Enum。解析以从字符串“OEM”和“CMB”中检索正确的DBGroupTypes值。然后,您可以将这些值转换为int,并从您希望在模型中进一步使用的正确枚举中检索正确的值。