我知道下面是不可能的,因为枚举的类型必须是int
enum GroupTypes
{
TheGroup = "OEM",
TheOtherGroup = "CMB"
}
从我的数据库中,我得到了一个不全面的代码字段(OEM和CMBs)。我想让这个字段成为一个枚举或其他可以理解的东西。因为如果目标是可读性,解决方案就应该简洁。
我还有其他选择吗?
我知道下面是不可能的,因为枚举的类型必须是int
enum GroupTypes
{
TheGroup = "OEM",
TheOtherGroup = "CMB"
}
从我的数据库中,我得到了一个不全面的代码字段(OEM和CMBs)。我想让这个字段成为一个枚举或其他可以理解的东西。因为如果目标是可读性,解决方案就应该简洁。
我还有其他选择吗?
当前回答
我喜欢在类中使用属性而不是方法,因为它们看起来更像枚举。
下面是一个Logger的例子:
public class LogCategory
{
private LogCategory(string value) { Value = value; }
public string Value { get; private set; }
public static LogCategory Trace { get { return new LogCategory("Trace"); } }
public static LogCategory Debug { get { return new LogCategory("Debug"); } }
public static LogCategory Info { get { return new LogCategory("Info"); } }
public static LogCategory Warning { get { return new LogCategory("Warning"); } }
public static LogCategory Error { get { return new LogCategory("Error"); } }
public override string ToString()
{
return Value;
}
}
传入类型安全的字符串值作为参数:
public static void Write(string message, LogCategory logCategory)
{
var log = new LogEntry { Message = message };
Logger.Write(log, logCategory.Value);
}
用法:
Logger.Write("This is almost like an enum.", LogCategory.Info);
其他回答
另一种处理这个问题的方法是,有一个枚举和一个字符串数组,将枚举值映射到字符串列表:
public enum GroupTypes
{
TheGroup = 0,
TheOtherGroup
}
string[] GroupTypesStr = {
"OEM",
"CMB"
};
你可以这样使用它:
Log.Write(GroupTypesStr[(int)GroupTypes.TheOtherGroup]);
它将提示CMB
优点:
简单干净的代码。 高性能(特别是与那些方法相比 使用类)
缺点:
易于混乱的列表时,编辑它,但这将是一个好的 短名单。
我只需创建一个字典,并使用代码作为键。
编辑:为了解决关于执行反向查找(查找键)的注释,这将不是非常有效。如果有必要,我将编写一个新类来处理它。
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; }
}
}
根据其他人的意见,这是我想到的。这种方法避免了在想要获得常量值的地方键入. 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属性
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;
}
}