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

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

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

我还有其他选择吗?


当前回答

public class DataType
{
    private readonly string value;
    private static readonly Dictionary<string, DataType> predefinedValues;

    public static readonly DataType Json = new DataType("json");
    public static readonly DataType Xml = new DataType("xml");
    public static readonly DataType Text = new DataType("text");
    public static readonly DataType Html = new DataType("html");
    public static readonly DataType Binary = new DataType("binary");

    static DataType()
    {
        predefinedValues = new Dictionary<string, DataType>();
        predefinedValues.Add(Json.Value, Json);
        predefinedValues.Add(Xml.Value, Xml);
        predefinedValues.Add(Text.Value, Text);
        predefinedValues.Add(Html.Value, Html);
        predefinedValues.Add(Binary.Value, Binary);
    }

    private DataType(string value)
    {
        this.value = value;
    }

    public static DataType Parse(string value)
    {
        var exception = new FormatException($"Invalid value for type {nameof(DataType)}");
        if (string.IsNullOrEmpty(value))
            throw exception;

        string key = value.ToLower();
        if (!predefinedValues.ContainsKey(key))
            throw exception;

        return predefinedValues[key];
    }

    public string Value
    {
        get { return value; }
    }
}

其他回答

. net Core 3.0/ c# 8.0(如果你的工作环境允许你升级你的项目)新增了一个简短的switch语句,看起来有点枚举。在一天结束的时候,这和我们多年来一直在使用的无聊的开关语句是一样的。

这里唯一真正的区别是switch语句得到了一个新的suit。

public static RGBColor FromRainbow(Rainbow colorBand) =>
colorBand switch
{
    Rainbow.Red    => new RGBColor(0xFF, 0x00, 0x00),
    Rainbow.Orange => new RGBColor(0xFF, 0x7F, 0x00),
    Rainbow.Yellow => new RGBColor(0xFF, 0xFF, 0x00),
    Rainbow.Green  => new RGBColor(0x00, 0xFF, 0x00),
    Rainbow.Blue   => new RGBColor(0x00, 0x00, 0xFF),
    Rainbow.Indigo => new RGBColor(0x4B, 0x00, 0x82),
    Rainbow.Violet => new RGBColor(0x94, 0x00, 0xD3),
    _              => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)),
};

你会注意到上面我从这里复制的代码,实际上是使用一个枚举作为参数。

这并不是您想要的(相信我,我早就想要类似OP要求的东西了),但我实际上觉得这是MS. JMO抛出的橄榄枝。

希望它能帮助到一些人!

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

另一种处理这个问题的方法是,有一个枚举和一个字符串数组,将枚举值映射到字符串列表:

public enum GroupTypes
{
    TheGroup  = 0,
    TheOtherGroup 
}

string[] GroupTypesStr = {
    "OEM",
    "CMB"
};

你可以这样使用它:

Log.Write(GroupTypesStr[(int)GroupTypes.TheOtherGroup]);

它将提示CMB

优点:

简单干净的代码。 高性能(特别是与那些方法相比 使用类)

缺点:

易于混乱的列表时,编辑它,但这将是一个好的 短名单。

在VS 2015中,你可以使用nameof

public class LogCategory
{
    public static string Trace;
    public static string Debug;
    public static string Info;
    public static string Warning;
    public static string Error;
}

用法:

Logger.Write("This is almost like an enum.", nameof(LogCategory.Info));

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

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()在读取字符串时查找它。