我知道下面是不可能的,因为枚举的类型必须是int
enum GroupTypes
{
TheGroup = "OEM",
TheOtherGroup = "CMB"
}
从我的数据库中,我得到了一个不全面的代码字段(OEM和CMBs)。我想让这个字段成为一个枚举或其他可以理解的东西。因为如果目标是可读性,解决方案就应该简洁。
我还有其他选择吗?
我知道下面是不可能的,因为枚举的类型必须是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属性