将枚举与 C# 中的字符串关联起来
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/630803/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Associating enums with strings in C#
提问by Boris Callens
I know the following is not possible because the Enumeration's type has to be an int
我知道以下是不可能的,因为枚举的类型必须是 int
enum GroupTypes
{
TheGroup = "OEM",
TheOtherGroup = "CMB"
}
From my database I get a field with incomprehensive codes (the OEM
and CMB
s). I would want to make this field into an enum
or something else understandable. Because if the target is readability, the solution should be terse.
从我的数据库中,我得到了一个包含不完整代码(theOEM
和CMB
s)的字段。我想让这个领域成为一个enum
或其他可以理解的东西。因为如果目标是可读性,那么解决方案应该是简洁的。
What other options do I have?
我还有什么其他选择?
采纳答案by Even Mien
I like to use properties in a classinstead of methods, since they look more enum-like.
我喜欢在类中使用属性而不是方法,因为它们看起来更像枚举。
Here's a example for a Logger:
下面是一个 Logger 的例子:
public class LogCategory
{
private LogCategory(string value) { Value = value; }
public string Value { get; 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"); } }
}
Pass in type-safe string valuesas a parameter:
将类型安全的字符串值作为参数传递:
public static void Write(string message, LogCategory logCategory)
{
var log = new LogEntry { Message = message };
Logger.Write(log, logCategory.Value);
}
Usage:
用法:
Logger.Write("This is almost like an enum.", LogCategory.Info);
回答by jhale
I would just create a dictionary and use the code as the key.
我只想创建一个字典并使用代码作为键。
Edit: To address the comment about doing a reverse lookup (finding the key), this would not be terribly efficient. If this is necessary, I would write a new class to handle it.
编辑:为了解决关于进行反向查找(找到密钥)的评论,这不会非常有效。如果有必要,我会编写一个新类来处理它。
回答by Dave Van den Eynde
Create a second enum, for your DB containing the following:
为包含以下内容的数据库创建第二个枚举:
enum DBGroupTypes
{
OEM = 0,
CMB = 1
}
Now, you can use Enum.Parse to retrieve the correct DBGroupTypes value from the strings "OEM" and "CMB". You can then convert those to int and retrieve the correct values from the right enumeration you want to use further in your model.
现在,您可以使用 Enum.Parse 从字符串“OEM”和“CMB”中检索正确的 DBGroupTypes 值。然后,您可以将它们转换为 int 并从要在模型中进一步使用的正确枚举中检索正确的值。
回答by casperOne
You can add attributes to the items in the enumeration and then use reflection to get the values from the attributes.
您可以为枚举中的项目添加属性,然后使用反射从属性中获取值。
You would have to use the "field" specifier to apply the attributes, like so:
您必须使用“字段”说明符来应用属性,如下所示:
enum GroupTypes
{
[field:Description("OEM")]
TheGroup,
[field:Description("CMB")]
TheOtherGroup
}
You would then reflect on the static fields of the type of the enum (in this case GroupTypes) and get the DescriptionAttribute
for the value you were looking for using reflection:
然后,您将反映枚举类型(在本例中为 GroupTypes)的静态字段,并DescriptionAttribute
使用反射获取您正在寻找的值:
public static DescriptionAttribute GetEnumDescriptionAttribute<T>(
this T value) where T : struct
{
// The type of the enum, it will be reused.
Type type = typeof(T);
// If T is not an enum, get out.
if (!type.IsEnum)
throw new InvalidOperationException(
"The type parameter T must be an enum type.");
// If the value isn't defined throw an exception.
if (!Enum.IsDefined(type, value))
throw new InvalidEnumArgumentException(
"value", Convert.ToInt32(value), type);
// Get the static field for the value.
FieldInfo fi = type.GetField(value.ToString(),
BindingFlags.Static | BindingFlags.Public);
// Get the description attribute, if there is one.
return fi.GetCustomAttributes(typeof(DescriptionAttribute), true).
Cast<DescriptionAttribute>().SingleOrDefault();
}
I opted to return the DescriptionAttribute
itself above, in the event that you want to be able to determine whether or not the attribute is even applied.
DescriptionAttribute
如果您希望能够确定是否甚至应用了该属性,我选择返回上面的本身。
回答by C. Ross
Use a class.
使用一个类。
Edit: Better example
编辑:更好的例子
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.");
}
}
回答by darasd
Try adding constants to a static class. You don't end up with a Type, but you will have readable, organised constants:
尝试向静态类添加常量。您不会以 Type 结束,但您将拥有可读的、有组织的常量:
public static class GroupTypes {
public const string TheGroup = "OEM";
public const string TheOtherGroup = "CMB";
}
回答by Jim Mischel
Have you considered a lookup table using a Dictionary?
您是否考虑过使用字典的查找表?
enum GroupTypes
{
TheGroup,
TheOtherGroup
}
Dictionary<string, GroupTypes> GroupTypeLookup = new Dictionary<string, GroupTypes>();
// initialize lookup table:
GroupTypeLookup.Add("OEM", TheGroup);
GroupTypeLookup.Add("CMB", TheOtherGroup);
You can then use GroupTypeLookup.TryGetValue() to look up a string when you read it.
然后,您可以在读取字符串时使用 GroupTypeLookup.TryGetValue() 来查找字符串。
回答by Bryan Rowe
I would make it into a class an avoid an enum altogether. And then with the usage of a typehandler you could create the object when you grab it from the db.
我会把它变成一个类,完全避免枚举。然后使用类型处理程序,您可以在从数据库中获取对象时创建该对象。
IE:
IE:
public class Group
{
public string Value{ get; set; }
public Group( string value ){ Value = value; }
public static Group TheGroup() { return new Group("OEM"); }
public static Group OtherGroup() { return new Group("CMB"); }
}
回答by Glennular
You could also use the extension model:
您还可以使用扩展模型:
public enum MyEnum
{
[Description("String 1")]
V1= 1,
[Description("String 2")]
V2= 2
}
Your Extension Class
你的扩展类
public static class MyEnumExtensions
{
public static string ToDescriptionString(this MyEnum val)
{
DescriptionAttribute[] attributes = (DescriptionAttribute[])val
.GetType()
.GetField(val.ToString())
.GetCustomAttributes(typeof(DescriptionAttribute), false);
return attributes.Length > 0 ? attributes[0].Description : string.Empty;
}
}
usage:
用法:
MyEnum myLocal = MyEnum.V1;
print(myLocal.ToDescriptionString());
回答by Reed Copsey
My first question - Do you have access to the Database itself? This should be normalized in the database, ideally, otherwise, any solution is going to be prone to error. In my experience, data fields full of "OEM" and "CMB" tend to wind up having things like "oem " and other 'crap data' mixed in over time.... If you can normalize it, you could use the key in the table containing the elements as your Enum, and you're done, with a much cleaner structure.
我的第一个问题 - 您可以访问数据库本身吗?理想情况下,这应该在数据库中规范化,否则任何解决方案都容易出错。根据我的经验,随着时间的推移,充满“OEM”和“CMB”的数据字段往往会混入诸如“oem”和其他“垃圾数据”之类的东西......如果你能将它标准化,你可以使用密钥在包含元素作为枚举的表中,您就完成了,结构更清晰。
If that's not available, I'd make your Enum, and make a class to parse your string into the Enum for you. This would at least give you some flexibility in handling non-standard entries and much more flexibility for trapping or handling errors than doing any of the workarounds using Enum.Parse/Reflection/etc. A dictionary would work, but could break down if you ever have case issues, etc.
如果那不可用,我会制作您的枚举,并创建一个类来为您将字符串解析为枚举。与使用 Enum.Parse/Reflection/etc 执行任何变通方法相比,这至少会给您一些处理非标准条目的灵活性,以及更多的捕获或处理错误的灵活性。字典可以工作,但如果您遇到案例问题等,则可能会崩溃。
I'd recommend writing a class so you can do:
我建议编写一个类,以便您可以:
// I renamed this to GroupType, since it sounds like each element has a single type...
GroupType theType = GroupTypeParser.GetGroupType(theDBString);
This preserves most of your readability without having to change the DB.
这可以保留大部分可读性,而无需更改数据库。