String representation of an Enum
我有以下列举:
1 2 3 4 5 6 | public enum AuthenticationMethod { FORMS = 1, WINDOWSAUTHENTICATION = 2, SINGLESIGNON = 3 } |
然而,问题是,当我请求authenticationMethod.forms而不是ID 1时,我需要单词"forms"。
我已找到此问题的以下解决方案(链接):
首先,我需要创建一个名为"stringvalue"的自定义属性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class StringValue : System.Attribute { private readonly string _value; public StringValue(string value) { _value = value; } public string Value { get { return _value; } } } |
然后我可以将此属性添加到枚举器中:
1 2 3 4 5 6 7 8 9 | public enum AuthenticationMethod { [StringValue("FORMS")] FORMS = 1, [StringValue("WINDOWS")] WINDOWSAUTHENTICATION = 2, [StringValue("SSO")] SINGLESIGNON = 3 } |
当然,我需要一些东西来检索这个字符串值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public static class StringEnum { public static string GetStringValue(Enum value) { string output = null; Type type = value.GetType(); //Check first in our cached results... //Look for our 'StringValueAttribute' //in the field's custom attributes FieldInfo fi = type.GetField(value.ToString()); StringValue[] attrs = fi.GetCustomAttributes(typeof(StringValue), false) as StringValue[]; if (attrs.Length > 0) { output = attrs[0].Value; } return output; } } |
很好,现在我有了获取枚举器字符串值的工具。然后我可以这样使用它:
1 | string valueOfAuthenticationMethod = StringEnum.GetStringValue(AuthenticationMethod.FORMS); |
好吧,现在所有这些工作都很有魅力,但我发现它需要很多工作。我想知道是否有更好的解决办法。
我也用字典和静态属性做了一些尝试,但这也不是更好。
尝试键入安全枚举模式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public sealed class AuthenticationMethod { private readonly String name; private readonly int value; public static readonly AuthenticationMethod FORMS = new AuthenticationMethod (1,"FORMS"); public static readonly AuthenticationMethod WINDOWSAUTHENTICATION = new AuthenticationMethod (2,"WINDOWS"); public static readonly AuthenticationMethod SINGLESIGNON = new AuthenticationMethod (3,"SSN"); private AuthenticationMethod(int value, String name){ this.name = name; this.value = value; } public override String ToString(){ return name; } } |
更新显式(或隐式)类型转换可以通过
使用映射添加静态字段
1private static readonly Dictionary<string, AuthenticationMethod> instance = new Dictionary<string,AuthenticationMethod>();- 注意,"枚举成员"字段的初始化在调用实例构造函数时不会引发NullReferenceException,请确保将字典字段放在类中的"枚举成员"字段之前。这是因为静态字段初始化器是按声明顺序调用的,在静态构造函数之前,创建了一种奇怪的、必要的但令人困惑的情况,即可以在初始化所有静态字段之前和调用静态构造函数之前调用实例构造函数。
在实例构造函数中填充此映射
1instance[name] = this;并添加用户定义的类型转换运算符
1
2
3
4
5
6
7
8public static explicit operator AuthenticationMethod(string str)
{
AuthenticationMethod result;
if (instance.TryGetValue(str, out result))
return result;
else
throw new InvalidCastException();
}
使用方法
1 | Enum.GetName(Type MyEnumType, object enumvariable) |
如(假设
1 2 |
枚举类上还有许多其他静态方法值得研究…
可以使用ToString()引用名称而不是值
1 | Console.WriteLine("Auth method: {0}", AuthenticationMethod.Forms.ToString()); |
文件如下:
http://msdn.microsoft.com/en-us/library/16c1xs4z.aspx
…如果您在pascal情况下命名枚举(如thisismyNumValue=1等),则可以使用非常简单的regex打印友好的表单:
1 2 3 4 | static string ToFriendlyCase(this string EnumString) { return Regex.Replace(EnumString,"(?!^)([A-Z])"," $1"); } |
可以从任何字符串轻松调用:
1 | Console.WriteLine("ConvertMyCrazyPascalCaseSentenceToFriendlyCase".ToFriendlyCase()); |
输出:
Convert My Crazy Pascal Case Sentence To Friendly Case
这节省了在房屋周围运行创建自定义属性并将它们附加到枚举中,或者使用查找表将枚举值与友好的字符串结合在一起(最好是它的自我管理),并且可以用于任何更加可重用的pascal case字符串。当然,它不允许您使用与解决方案提供的枚举不同的友好名称。
不过,对于更复杂的场景,我确实喜欢您的原始解决方案。您可以进一步研究解决方案,使GetStringValue成为枚举的扩展方法,然后您就不需要像StringEnum.GetStringValue那样引用它了…
1 2 3 4 5 6 7 8 9 10 | public static string GetStringValue(this AuthenticationMethod value) { string output = null; Type type = value.GetType(); FieldInfo fi = type.GetField(value.ToString()); StringValue[] attrs = fi.GetCustomAttributes(typeof(StringValue), false) as StringValue[]; if (attrs.Length > 0) output = attrs[0].Value; return output; } |
然后可以直接从枚举实例轻松访问它:
1 | Console.WriteLine(AuthenticationMethod.SSO.GetStringValue()); |
不幸的是,在枚举上获取属性的反射非常慢:
看到这个问题:有人知道一种快速的方法来获取枚举值的自定义属性吗?
但是,您可以编写枚举的扩展方法:
1 2 3 4 5 6 7 | public static string GetName( this MyEnum input ) { switch ( input ) { case MyEnum.WINDOWSAUTHENTICATION: return"Windows"; //and so on } } |
这不太好,但速度很快,不需要对属性或字段名进行反射。
C 6更新
如果您可以使用c 6,那么新的
注意,这会将显式枚举转换为内联常量,因此对于变量中的枚举不起作用。所以:
1 |
但是…
1 2 |
我使用扩展方法:
1 2 3 4 5 6 7 8 | public static class AttributesHelperExtension { public static string ToDescription(this Enum value) { var da = (DescriptionAttribute[])(value.GetType().GetField(value.ToString())).GetCustomAttributes(typeof(DescriptionAttribute), false); return da.Length > 0 ? da[0].Description : value.ToString(); } } |
现在用以下材料装饰
1 2 3 4 5 6 7 8 9 | public enum AuthenticationMethod { [Description("FORMS")] FORMS = 1, [Description("WINDOWSAUTHENTICATION")] WINDOWSAUTHENTICATION = 2, [Description("SINGLESIGNON")] SINGLESIGNON = 3 } |
当你打电话
你会得到
只需使用
1 | public enum any{Tomato=0,Melon,Watermelon} |
要引用字符串
1 | any.Tomato.ToString(); |
我使用system.componentModel命名空间中的description属性。只需修饰枚举,然后使用此代码检索它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public static string GetDescription<T>(this object enumerationValue) where T : struct { Type type = enumerationValue.GetType(); if (!type.IsEnum) { throw new ArgumentException("EnumerationValue must be of Enum type","enumerationValue"); } //Tries to find a DescriptionAttribute for a potential friendly name //for the enum MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString()); if (memberInfo != null && memberInfo.Length > 0) { object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); if (attrs != null && attrs.Length > 0) { //Pull out the description value return ((DescriptionAttribute)attrs[0]).Description; } } //If we have no description attribute, just return the ToString of the enum return enumerationValue.ToString(); } |
举个例子:
1 2 3 4 5 6 7 | public enum Cycle : int { [Description("Daily Cycle")] Daily = 1, Weekly, Monthly } |
此代码很好地满足了不需要"友好名称"的枚举,并且只返回枚举的.toString()。
非常简单的.NET 4.0及更高版本的解决方案。不需要其他代码。
1 2 3 4 5 | public enum MyStatus { Active = 1, Archived = 2 } |
要获取关于just use的字符串:
1 | MyStatus.Active.ToString("f"); |
或
1 | MyStatus.Archived.ToString("f");` |
该值将为"活动"或"存档"。
要在调用
我真的喜欢杰克?Turc的答案,但它的缺点是不能将它与switch case语句一起使用。下面是一个稍微修改过的答案版本,可以与switch语句一起使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | public sealed class AuthenticationMethod { #region This code never needs to change. private readonly string _name; public readonly Values Value; private AuthenticationMethod(Values value, String name){ this._name = name; this.Value = value; } public override String ToString(){ return _name; } #endregion public enum Values { Forms = 1, Windows = 2, SSN = 3 } public static readonly AuthenticationMethod FORMS = new AuthenticationMethod (Values.Forms,"FORMS"); public static readonly AuthenticationMethod WINDOWSAUTHENTICATION = new AuthenticationMethod (Values.Windows,"WINDOWS"); public static readonly AuthenticationMethod SINGLESIGNON = new AuthenticationMethod (Values.SSN,"SSN"); } |
所以你得到了雅库布的所有好处?Turc的答案,另外,我们可以将其与如下switch语句一起使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 | var authenticationMethodVariable = AuthenticationMethod.FORMS; // Set the"enum" value we want to use. var methodName = authenticationMethodVariable.ToString(); // Get the user-friendly"name" of the"enum" value. // Perform logic based on which"enum" value was chosen. switch (authenticationMethodVariable.Value) { case authenticationMethodVariable.Values.Forms: // Do something break; case authenticationMethodVariable.Values.Windows: // Do something break; case authenticationMethodVariable.Values.SSN: // Do something break; } |
在您的问题中,您从未说过您实际上需要枚举的任何位置的数值。
如果您不需要并且只需要一个string类型的枚举(它不是整型的,因此不能是枚举的基),下面是一种方法:
1 2 3 4 5 6 | static class AuthenticationMethod { public static readonly string FORMS ="Forms", WINDOWSAUTHENTICATION ="WindowsAuthentication"; } |
可以使用与枚举相同的语法来引用它
1 | if (bla == AuthenticationMethod.FORMS) |
它将比数值(比较字符串而不是数字)慢一点,但在正方面,它不使用反射(慢)来访问字符串。
我结合使用上面的几个建议,并结合一些缓存。现在,我从网上某个地方找到的代码中得到了这个想法,但是我不记得从哪里得到的或者找到的。因此,如果有人发现类似的东西,请评论其属性。
不管怎样,这种用法涉及类型转换器,因此如果您绑定到UI,它就"正常工作"。通过从类型转换器初始化为静态方法,可以使用Jakub的模式进行扩展,以便快速查找代码。
基本用法如下
1 2 3 4 5 6 7 8 9 10 | [TypeConverter(typeof(CustomEnumTypeConverter<MyEnum>))] public enum MyEnum { // The custom type converter will use the description attribute [Description("A custom description")] ValueWithCustomDescription, // This will be exposed exactly. Exact } |
自定义枚举类型转换器的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | public class CustomEnumTypeConverter<T> : EnumConverter where T : struct { private static readonly Dictionary<T,string> s_toString = new Dictionary<T, string>(); private static readonly Dictionary<string, T> s_toValue = new Dictionary<string, T>(); private static bool s_isInitialized; static CustomEnumTypeConverter() { System.Diagnostics.Debug.Assert(typeof(T).IsEnum, "The custom enum class must be used with an enum type."); } public CustomEnumTypeConverter() : base(typeof(T)) { if (!s_isInitialized) { Initialize(); s_isInitialized = true; } } protected void Initialize() { foreach (T item in Enum.GetValues(typeof(T))) { string description = GetDescription(item); s_toString[item] = description; s_toValue[description] = item; } } private static string GetDescription(T optionValue) { var optionDescription = optionValue.ToString(); var optionInfo = typeof(T).GetField(optionDescription); if (Attribute.IsDefined(optionInfo, typeof(DescriptionAttribute))) { var attribute = (DescriptionAttribute)Attribute. GetCustomAttribute(optionInfo, typeof(DescriptionAttribute)); return attribute.Description; } return optionDescription; } public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) { var optionValue = (T)value; if (destinationType == typeof(string) && s_toString.ContainsKey(optionValue)) { return s_toString[optionValue]; } return base.ConvertTo(context, culture, value, destinationType); } public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) { var stringValue = value as string; if (!string.IsNullOrEmpty(stringValue) && s_toValue.ContainsKey(stringValue)) { return s_toValue[stringValue]; } return base.ConvertFrom(context, culture, value); } } |
}
作为你们大多数人,我真的很喜欢杰克选择的答案?但是我也很讨厌复制粘贴代码,并且尽可能少地做。
所以我决定要一个Enumbase类,其中大部分功能都是继承/内置的,这让我只关注内容而不是行为。
这种方法的主要问题是基于这样一个事实:尽管枚举值是类型安全的实例,但是交互是与枚举类类型的静态实现进行的。所以在仿制药的帮助下,我想我终于得到了正确的组合。希望有人能像我一样发现这一点。
我将从Jakub的例子开始,但使用继承和泛型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public sealed class AuthenticationMethod : EnumBase<AuthenticationMethod, int> { public static readonly AuthenticationMethod FORMS = new AuthenticationMethod(1,"FORMS"); public static readonly AuthenticationMethod WINDOWSAUTHENTICATION = new AuthenticationMethod(2,"WINDOWS"); public static readonly AuthenticationMethod SINGLESIGNON = new AuthenticationMethod(3,"SSN"); private AuthenticationMethod(int Value, String Name) : base( Value, Name ) { } public new static IEnumerable<AuthenticationMethod> All { get { return EnumBase<AuthenticationMethod, int>.All; } } public static explicit operator AuthenticationMethod(string str) { return Parse(str); } } |
下面是基本类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | using System; using System.Collections.Generic; using System.Linq; // for the .AsEnumerable() method call // E is the derived type-safe-enum class // - this allows all static members to be truly unique to the specific // derived class public class EnumBase<E, T> where E: EnumBase<E, T> { #region Instance code public T Value { get; private set; } public string Name { get; private set; } protected EnumBase(T EnumValue, string Name) { Value = EnumValue; this.Name = Name; mapping.Add(Name, this); } public override string ToString() { return Name; } #endregion #region Static tools static private readonly Dictionary<string, EnumBase<E, T>> mapping; static EnumBase() { mapping = new Dictionary<string, EnumBase<E, T>>(); } protected static E Parse(string name) { EnumBase<E, T> result; if (mapping.TryGetValue(name, out result)) { return (E)result; } throw new InvalidCastException(); } // This is protected to force the child class to expose it's own static // method. // By recreating this static method at the derived class, static // initialization will be explicit, promising the mapping dictionary // will never be empty when this method is called. protected static IEnumerable<E> All { get { return mapping.Values.AsEnumerable().Cast<E>(); } } #endregion } |
我如何将此作为扩展方法来解决:
1 2 3 4 5 6 7 8 9 10 11 | using System.ComponentModel; public static string GetDescription(this Enum value) { var descriptionAttribute = (DescriptionAttribute)value.GetType() .GetField(value.ToString()) .GetCustomAttributes(false) .Where(a => a is DescriptionAttribute) .FirstOrDefault(); return descriptionAttribute != null ? descriptionAttribute.Description : value.ToString(); } |
枚举:
1 2 3 4 5 6 7 8 | public enum OrderType { None = 0, [Description("New Card")] NewCard = 1, [Description("Reload")] Refill = 2 } |
用法(其中o.orderType是与枚举同名的属性):
1 | o.OrderType.GetDescription() |
它给我一个字符串"new card"或"reload",而不是实际的枚举值new card并重新填充。
我同意基思的观点,但我还不能投票。
我使用静态方法和swith语句返回我想要的。在我存储tinyint的数据库中,我的代码只使用实际的枚举,因此字符串是用于UI需求的。经过多次测试,这导致了最佳的性能和对输出的大部分控制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public static string ToSimpleString(this enum) { switch (enum) { case ComplexForms: return"ComplexForms"; break; } } public static string ToFormattedString(this enum) { switch (enum) { case ComplexForms: return"Complex Forms"; break; } } |
但是,根据一些说法,这会导致可能的维护噩梦和一些代码气味。我试着留意那些长的和很多的枚举,或者那些经常变化的枚举。否则,这对我来说是个很好的解决方案。
如果您来这里希望实现一个简单的"枚举",但其值是字符串而不是整数,那么这里是最简单的解决方案:
1 2 3 4 5 | public sealed class MetricValueList { public static readonly string Brand ="A4082457-D467-E111-98DC-0026B9010912"; public static readonly string Name ="B5B5E167-D467-E111-98DC-0026B9010912"; } |
实施:
1 | var someStringVariable = MetricValueList.Brand; |
我想在下面引用的帖子上发表评论,但不能,因为我没有足够的代表-所以请不要拒绝投票。代码包含一个错误,我想向试图使用此解决方案的个人指出这一点:
应该是
1 2 3 4 5 6 7 8 9 10 | [TypeConverter(typeof(CustomEnumTypeConverter<MyEnum>))] public enum MyEnum { // The custom type converter will use the description attribute [Description("A custom description")] ValueWithCustomDescription, // This will be exposed exactly. Exact } |
闪耀!
当我遇到这个问题时,有几个问题我试图找到第一个问题的答案:
- 我的枚举值的名称是否足够友好,或者我是否需要提供更友好的名称?
- 我需要往返吗?也就是说,我需要获取文本值并将其解析为枚举值吗?
- 在我的项目中,这是我需要为许多枚举做的事情,还是只需要一个?
- 我将呈现哪些类型的UI元素—特别是,我将绑定到UI,还是使用属性表?
- 这需要本地化吗?
最简单的方法是使用
一般来说,如果上述问题的答案表明这行不通,我的下一步就是创建和填充一个静态的
我的变体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | public struct Colors { private String current; private static string red ="#ff0000"; private static string green ="#00ff00"; private static string blue ="#0000ff"; private static IList<String> possibleColors; public static Colors Red { get { return (Colors) red; } } public static Colors Green { get { return (Colors) green; } } public static Colors Blue { get { return (Colors) blue; } } static Colors() { possibleColors = new List<string>() {red, green, blue}; } public static explicit operator String(Colors value) { return value.current; } public static explicit operator Colors(String value) { if (!possibleColors.Contains(value)) { throw new InvalidCastException(); } Colors color = new Colors(); color.current = value; return color; } public static bool operator ==(Colors left, Colors right) { return left.current == right.current; } public static bool operator !=(Colors left, Colors right) { return left.current != right.current; } public bool Equals(Colors other) { return Equals(other.current, current); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (obj.GetType() != typeof(Colors)) return false; return Equals((Colors)obj); } public override int GetHashCode() { return (current != null ? current.GetHashCode() : 0); } public override string ToString() { return current; } } |
代码看起来有点难看,但是这个结构的用法非常具有代表性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Colors color1 = Colors.Red; Console.WriteLine(color1); // #ff0000 Colors color2 = (Colors)"#00ff00"; Console.WriteLine(color2); // #00ff00 // Colors color3 ="#0000ff"; // Compilation error // String color4 = Colors.Red; // Compilation error Colors color5 = (Colors)"#ff0000"; Console.WriteLine(color1 == color5); // True Colors color6 = (Colors)"#00ff00"; Console.WriteLine(color1 == color6); // False |
此外,我认为,如果需要大量这样的枚举,可能会使用代码生成(例如t4)。
选项1:
1 2 3 4 5 6 7 8 9 10 11 12 13 | public sealed class FormsAuth { public override string ToString{return"Forms Authtentication";} } public sealed class WindowsAuth { public override string ToString{return"Windows Authtentication";} } public sealed class SsoAuth { public override string ToString{return"SSO";} } |
然后
1 2 3 4 5 6 7 | object auth = new SsoAuth(); //or whatever //... //... // blablabla DoSomethingWithTheAuth(auth.ToString()); |
选项2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public enum AuthenticationMethod { FORMS = 1, WINDOWSAUTHENTICATION = 2, SINGLESIGNON = 3 } public class MyClass { private Dictionary<AuthenticationMethod, String> map = new Dictionary<AuthenticationMethod, String>(); public MyClass() { map.Add(AuthenticationMethod.FORMS,"Forms Authentication"); map.Add(AuthenticationMethod.WINDOWSAUTHENTICATION ,"Windows Authentication"); map.Add(AuthenticationMethod.SINGLESIGNON ,"SSo Authentication"); } } |
如果你考虑一下我们要解决的问题,它根本不是我们需要的枚举。我们需要一个允许一定数量的值相互关联的对象;换句话说,定义一个类。
Jakub?TURC的类型安全枚举模式是我在这里看到的最佳选项。
看看它:
- 它有一个私有的构造函数,因此只有类本身才能定义允许的值。
- 它是一个密封类,因此不能通过继承来修改值。
- 它是类型安全的,允许您的方法只需要该类型。
- 访问这些值不会影响反射性能。
- 最后,可以修改它,将两个以上的字段关联在一起,例如名称、描述和数值。
对于我来说,实用主义方法是类内的类,示例:
1 2 3 4 5 6 7 8 9 10 11 12 | public class MSEModel { class WITS { public const string DATE ="5005"; public const string TIME ="5006"; public const string MD ="5008"; public const string ROP ="5075"; public const string WOB ="5073"; public const string RPM ="7001"; ... } |
下面是另一种完成字符串与枚举关联任务的方法:
1 2 3 4 5 6 7 8 9 | struct DATABASE { public enum enums {NOTCONNECTED, CONNECTED, ERROR} static List<string> strings = new List<string>() {"Not Connected","Connected","Error"}; public string GetString(DATABASE.enums value) { return strings[(int)value]; } } |
此方法的调用方式如下:
1 2 3 4 5 | public FormMain() { DATABASE dbEnum; string enumName = dbEnum.GetString(DATABASE.enums.NOTCONNECTED); } |
可以将相关枚举分组到它们自己的结构中。由于此方法使用枚举类型,因此在进行
您可以选择在
这里有很多很好的答案,但在我的例子中,没有解决我想要的"字符串枚举",即:
1,2&4实际上可以用字符串的c typedef来解决(因为字符串可以在c中切换)
3可以通过静态常量字符串来解决。因此,如果您有相同的需求,这是最简单的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | public sealed class Types { private readonly String name; private Types(String name) { this.name = name; } public override String ToString() { return name; } public static implicit operator Types(string str) { return new Types(str); } public static implicit operator string(Types str) { return str.ToString(); } #region enum public const string DataType ="Data"; public const string ImageType ="Image"; public const string Folder ="Folder"; #endregion } |
例如,这允许:
1 2 3 4 | public TypeArgs(Types SelectedType) { Types SelectedType = SelectedType } |
和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public TypeObject CreateType(Types type) { switch (type) { case Types.ImageType: // break; case Types.DataType: // break; } } |
其中,可以使用字符串或类型调用CreateType。但是,缺点是任何字符串都是自动有效的枚举,可以修改它,但是它将需要某种类型的init函数…或者可能使它们显式转换为内部的?
现在,如果一个int值对您很重要(可能是为了比较速度),您可以使用Jakub的一些想法吗?你的回答太好了,做点疯狂的事,这是我的一个尝试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | public sealed class Types { private static readonly Dictionary<string, Types> strInstance = new Dictionary<string, Types>(); private static readonly Dictionary<int, Types> intInstance = new Dictionary<int, Types>(); private readonly String name; private static int layerTypeCount = 0; private int value; private Types(String name) { this.name = name; value = layerTypeCount++; strInstance[name] = this; intInstance[value] = this; } public override String ToString() { return name; } public static implicit operator Types(int val) { Types result; if (intInstance.TryGetValue(val, out result)) return result; else throw new InvalidCastException(); } public static implicit operator Types(string str) { Types result; if (strInstance.TryGetValue(str, out result)) { return result; } else { result = new Types(str); return result; } } public static implicit operator string(Types str) { return str.ToString(); } public static bool operator ==(Types a, Types b) { return a.value == b.value; } public static bool operator !=(Types a, Types b) { return a.value != b.value; } #region enum public const string DataType ="Data"; public const string ImageType ="Image"; #endregion } |
但当然,"types bob=4;"将毫无意义,除非您先初始化它们,这将有点破坏要点…
但理论上,typeA==typeB会更快…
如果我对您的理解正确,您可以简单地使用.toString()从值中检索枚举的名称(假设它已经转换为枚举);如果有naked int(比如从数据库或其他地方),可以首先将其强制转换为枚举。下面的两个方法都将获得枚举名称。
1 2 3 4 | AuthenticationMethod myCurrentSetting = AuthenticationMethod.FORMS; Console.WriteLine(myCurrentSetting); // Prints: FORMS string name = Enum.GetNames(typeof(AuthenticationMethod))[(int)myCurrentSetting-1]; Console.WriteLine(name); // Prints: FORMS |
不过请记住,第二种技术假定您使用的是int,并且您的索引是基于1的(而不是基于0的)。相比之下,getname函数也很重,每次调用它时都会生成一个完整的数组。正如您在第一个技术中看到的那样,.toString()实际上是隐式调用的。当然,答案中已经提到了这两个问题,我只是想澄清它们之间的区别。
老职位但是…
答案可能非常简单。使用Enum.ToString()函数
此函数有6个重载,可以使用Enum.ToString("f")或Enum.ToString()返回字符串值。不必为别的事费心。这是一个有效的演示
请注意,此解决方案可能不适用于所有编译器(此演示无法按预期工作),但至少适用于最新的编译器。
当我遇到这样的情况时,我会提出下面的解决方案。
作为一个消费阶层,你可以
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyApp.Dictionaries { class Greek { public static readonly string Alpha ="Alpha"; public static readonly string Beta ="Beta"; public static readonly string Gamma ="Gamma"; public static readonly string Delta ="Delta"; private static readonly BiDictionary<int, string> Dictionary = new BiDictionary<int, string>(); static Greek() { Dictionary.Add(1, Alpha); Dictionary.Add(2, Beta); Dictionary.Add(3, Gamma); Dictionary.Add(4, Delta); } public static string getById(int id){ return Dictionary.GetByFirst(id); } public static int getByValue(string value) { return Dictionary.GetBySecond(value); } } } |
使用双向字典:基于此(https://stackoverflow.com/a/255638/986160),假设这些键将与字典中的单个值关联,并且类似于(https://stackoverflow.com/a/255630/986160),但更优雅一些。这本字典也是可枚举的,您可以从int到strings来回查找。另外,除了这个类之外,代码库中不需要任何字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; namespace MyApp.Dictionaries { class BiDictionary<TFirst, TSecond> : IEnumerable { IDictionary<TFirst, TSecond> firstToSecond = new Dictionary<TFirst, TSecond>(); IDictionary<TSecond, TFirst> secondToFirst = new Dictionary<TSecond, TFirst>(); public void Add(TFirst first, TSecond second) { firstToSecond.Add(first, second); secondToFirst.Add(second, first); } public TSecond this[TFirst first] { get { return GetByFirst(first); } } public TFirst this[TSecond second] { get { return GetBySecond(second); } } public TSecond GetByFirst(TFirst first) { return firstToSecond[first]; } public TFirst GetBySecond(TSecond second) { return secondToFirst[second]; } public IEnumerator GetEnumerator() { return GetFirstEnumerator(); } public IEnumerator GetFirstEnumerator() { return firstToSecond.GetEnumerator(); } public IEnumerator GetSecondEnumerator() { return secondToFirst.GetEnumerator(); } } } |
好吧,在阅读了以上所有内容之后,我觉得这些人把枚举器转换成字符串的问题过于复杂了。我喜欢在枚举字段上拥有属性的想法,但我认为属性主要用于元数据,但在您的例子中,我认为您所需要的只是某种本地化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public enum Color { Red = 1, Green = 2, Blue = 3} public static EnumUtils { public static string GetEnumResourceString(object enumValue) { Type enumType = enumValue.GetType(); string value = Enum.GetName(enumValue.GetType(), enumValue); string resourceKey = String.Format("{0}_{1}", enumType.Name, value); string result = Resources.Enums.ResourceManager.GetString(resourceKey); if (string.IsNullOrEmpty(result)) { result = String.Format("{0}", value); } return result; } } |
现在,如果我们尝试调用上面的方法,我们可以这样调用它
1 2 3 4 5 | public void Foo() { var col = Color.Red; Console.WriteLine (EnumUtils.GetEnumResourceString (col)); } |
只需创建一个包含所有枚举器值和相应字符串的资源文件
1 2 3 4 | Resource Name Resource Value Color_Red My String Color in Red Color_Blue Blueeey Color_Green Hulk Color |
这实际上是非常好的一点,如果您需要将应用程序本地化,这将非常有帮助,因为您所需要做的只是用新语言创建另一个资源文件!还有Voe la!
对于较大的字符串枚举集,列出的示例可能会变得令人厌烦。如果需要状态代码列表或其他基于字符串的枚举列表,则使用属性系统很烦人,配置带有自身实例的静态类也很烦人。对于我自己的解决方案,我使用了t4模板,以使使用字符串支持的枚举更容易。结果与httpmethod类的工作方式类似。
您可以这样使用它:
1 2 3 4 5 6 7 8 9 10 11 12 | string statusCode = ResponseStatusCode.SUCCESS; // Automatically converts to string when needed ResponseStatusCode codeByValueOf = ResponseStatusCode.ValueOf(statusCode); // Returns null if not found // Implements TypeConverter so you can use it with string conversion methods. var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(ResponseStatusCode)); ResponseStatusCode code = (ResponseStatusCode) converter.ConvertFromInvariantString(statusCode); // You can get a full list of the values bool canIterateOverValues = ResponseStatusCode.Values.Any(); // Comparisons are by value of the"Name" property. Not by memory pointer location. bool implementsByValueEqualsEqualsOperator ="SUCCESS" == ResponseStatusCode.SUCCESS; |
从一个enum.tt文件开始。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <#@ include file="StringEnum.ttinclude" #> <#+ public static class Configuration { public static readonly string Namespace ="YourName.Space"; public static readonly string EnumName ="ResponseStatusCode"; public static readonly bool IncludeComments = true; public static readonly object Nodes = new { SUCCESS ="The response was successful.", NON_SUCCESS ="The request was not successful.", RESOURCE_IS_DISCONTINUED ="The resource requested has been discontinued and can no longer be accessed." }; } #> |
然后,添加StringEnum.ttinclude文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | <#@ template debug="false" hostspecific="false" language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Reflection" #> <#@ import namespace="System.Collections.Generic" #> <#@ output extension=".cs" #> <#@ CleanupBehavior processor="T4VSHost" CleanupAfterProcessingtemplate="true" #> //------------------------------------------------------------------------------ // // This code was generated by a tool. // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </auto-generated> //------------------------------------------------------------------------------ using System; using System.Linq; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; namespace <#= Configuration.Namespace #> { /// <summary> /// TypeConverter implementations allow you to use features like string.ToNullable(T). /// </summary> public class <#= Configuration.EnumName #>TypeConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { var casted = value as string; if (casted != null) { var result = <#= Configuration.EnumName #>.ValueOf(casted); if (result != null) { return result; } } return base.ConvertFrom(context, culture, value); } public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { var casted = value as <#= Configuration.EnumName #>; if (casted != null && destinationType == typeof(string)) { return casted.ToString(); } return base.ConvertTo(context, culture, value, destinationType); } } [TypeConverter(typeof(<#= Configuration.EnumName #>TypeConverter))] public class <#= Configuration.EnumName #> : IEquatable<<#= Configuration.EnumName #>> { //--------------------------------------------------------------------------------------------------- // V A L U E S _ L I S T //--------------------------------------------------------------------------------------------------- <# Write(Helpers.PrintEnumProperties(Configuration.Nodes)); #> private static List<<#= Configuration.EnumName #>> _list { get; set; } = null; public static List<<#= Configuration.EnumName #>> ToList() { if (_list == null) { _list = typeof(<#= Configuration.EnumName #>).GetFields().Where(x => x.IsStatic && x.IsPublic && x.FieldType == typeof(<#= Configuration.EnumName #>)) .Select(x => x.GetValue(null)).OfType<<#= Configuration.EnumName #>>().ToList(); } return _list; } public static List<<#= Configuration.EnumName #>> Values() { return ToList(); } /// <summary> /// Returns the enum value based on the matching Name of the enum. Case-insensitive search. /// </summary> /// <param name="key"></param> /// <returns></returns> public static <#= Configuration.EnumName #> ValueOf(string key) { return ToList().FirstOrDefault(x => string.Compare(x.Name, key, true) == 0); } //--------------------------------------------------------------------------------------------------- // I N S T A N C E _ D E F I N I T I O N //--------------------------------------------------------------------------------------------------- public string Name { get; private set; } public string Description { get; private set; } public override string ToString() { return this.Name; } /// <summary> /// Implcitly converts to string. /// </summary> /// <param name="d"></param> public static implicit operator string(<#= Configuration.EnumName #> d) { return d.ToString(); } /// <summary> /// Compares based on the == method. Handles nulls gracefully. /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static bool operator !=(<#= Configuration.EnumName #> a, <#= Configuration.EnumName #> b) { return !(a == b); } /// <summary> /// Compares based on the .Equals method. Handles nulls gracefully. /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static bool operator ==(<#= Configuration.EnumName #> a, <#= Configuration.EnumName #> b) { return a?.ToString() == b?.ToString(); } /// <summary> /// Compares based on the .ToString() method /// </summary> /// <param name="o"></param> /// <returns></returns> public override bool Equals(object o) { return this.ToString() == o?.ToString(); } /// <summary> /// Compares based on the .ToString() method /// </summary> /// <param name="other"></param> /// <returns></returns> public bool Equals(<#= Configuration.EnumName #> other) { return this.ToString() == other?.ToString(); } /// <summary> /// Compares based on the .Name property /// </summary> /// <returns></returns> public override int GetHashCode() { return this.Name.GetHashCode(); } } } <#+ public static class Helpers { public static string PrintEnumProperties(object nodes) { string o =""; Type nodesTp = Configuration.Nodes.GetType(); PropertyInfo[] props = nodesTp.GetProperties().OrderBy(p => p.Name).ToArray(); for(int i = 0; i < props.Length; i++) { var prop = props[i]; if (Configuration.IncludeComments) { o +=" "; o +=" ///<summary>"; o +=" ///"+Helpers.PrintPropertyValue(prop, Configuration.Nodes); o +=" ///</summary>"; } o +=" public static readonly"+Configuration.EnumName+""+prop.Name+" = new"+Configuration.EnumName+"(){ Name = ""+prop.Name+"", Description ="+Helpers.PrintPropertyValue(prop, Configuration.Nodes)+"};"; } o +=" "; return o; } private static Dictionary<string, string> GetValuesMap() { Type nodesTp = Configuration.Nodes.GetType(); PropertyInfo[] props= nodesTp.GetProperties(); var dic = new Dictionary<string,string>(); for(int i = 0; i < props.Length; i++) { var prop = nodesTp.GetProperties()[i]; dic[prop.Name] = prop.GetValue(Configuration.Nodes).ToString(); } return dic; } public static string PrintMasterValuesMap(object nodes) { Type nodesTp = Configuration.Nodes.GetType(); PropertyInfo[] props= nodesTp.GetProperties(); string o =" private static readonly Dictionary<string, string> ValuesMap = new Dictionary<string, string>() {"; for(int i = 0; i < props.Length; i++) { var prop = nodesTp.GetProperties()[i]; o +=" { ""+prop.Name+"","+(Helpers.PrintPropertyValue(prop,Configuration.Nodes)+" },"); } o += (" }; "); return o; } public static string PrintPropertyValue(PropertyInfo prop, object objInstance) { switch(prop.PropertyType.ToString()){ case"System.Double": return prop.GetValue(objInstance).ToString()+"D"; case"System.Float": return prop.GetValue(objInstance).ToString()+"F"; case"System.Decimal": return prop.GetValue(objInstance).ToString()+"M"; case"System.Long": return prop.GetValue(objInstance).ToString()+"L"; case"System.Boolean": case"System.Int16": case"System.Int32": return prop.GetValue(objInstance).ToString().ToLowerInvariant(); case"System.String": return"""+prop.GetValue(objInstance)+"""; } return prop.GetValue(objInstance).ToString(); } public static string _ (int numSpaces) { string o =""; for(int i = 0; i < numSpaces; i++){ o +=""; } return o; } } #> |
最后,重新编译enum.tt文件,输出如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | //------------------------------------------------------------------------------ // // This code was generated by a tool. // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </auto-generated> //------------------------------------------------------------------------------ using System; using System.Linq; using System.Collections.Generic; namespace YourName.Space { public class ResponseStatusCode { //--------------------------------------------------------------------------------------------------- // V A L U E S _ L I S T //--------------------------------------------------------------------------------------------------- ///<summary> ///"The response was successful." ///</summary> public static readonly ResponseStatusCode SUCCESS = new ResponseStatusCode(){ Name ="SUCCESS", Description ="The response was successful."}; ///<summary> ///"The request was not successful." ///</summary> public static readonly ResponseStatusCode NON_SUCCESS = new ResponseStatusCode(){ Name ="NON_SUCCESS", Description ="The request was not successful."}; ///<summary> ///"The resource requested has been discontinued and can no longer be accessed." ///</summary> public static readonly ResponseStatusCode RESOURCE_IS_DISCONTINUED = new ResponseStatusCode(){ Name ="RESOURCE_IS_DISCONTINUED", Description ="The resource requested has been discontinued and can no longer be accessed."}; private static List<ResponseStatusCode> _list { get; set; } = null; public static List<ResponseStatusCode> ToList() { if (_list == null) { _list = typeof(ResponseStatusCode).GetFields().Where(x => x.IsStatic && x.IsPublic && x.FieldType == typeof(ResponseStatusCode)) .Select(x => x.GetValue(null)).OfType<ResponseStatusCode>().ToList(); } return _list; } public static List<ResponseStatusCode> Values() { return ToList(); } /// <summary> /// Returns the enum value based on the matching Name of the enum. Case-insensitive search. /// </summary> /// <param name="key"></param> /// <returns></returns> public static ResponseStatusCode ValueOf(string key) { return ToList().FirstOrDefault(x => string.Compare(x.Name, key, true) == 0); } //--------------------------------------------------------------------------------------------------- // I N S T A N C E _ D E F I N I T I O N //--------------------------------------------------------------------------------------------------- public string Name { get; set; } public string Description { get; set; } public override string ToString() { return this.Name; } /// <summary> /// Implcitly converts to string. /// </summary> /// <param name="d"></param> public static implicit operator string(ResponseStatusCode d) { return d.ToString(); } /// <summary> /// Compares based on the == method. Handles nulls gracefully. /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static bool operator !=(ResponseStatusCode a, ResponseStatusCode b) { return !(a == b); } /// <summary> /// Compares based on the .Equals method. Handles nulls gracefully. /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static bool operator ==(ResponseStatusCode a, ResponseStatusCode b) { return a?.ToString() == b?.ToString(); } /// <summary> /// Compares based on the .ToString() method /// </summary> /// <param name="o"></param> /// <returns></returns> public override bool Equals(object o) { return this.ToString() == o?.ToString(); } /// <summary> /// Compares based on the .Name property /// </summary> /// <returns></returns> public override int GetHashCode() { return this.Name.GetHashCode(); } } } |
基于msdn:http://msdn.microsoft.com/en-us/library/cc138362.aspx
1 2 3 4 |
str将是字段的名称
我为枚举国际化或从各自的资源文件中获取枚举文本找到的方法是通过继承DescriptionAttribute类来创建一个属性类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class EnumResourceAttribute : DescriptionAttribute { public Type ResourceType { get; private set; } public string ResourceName { get; private set; } public int SortOrder { get; private set; } public EnumResourceAttribute(Type ResourceType, string ResourceName, int SortOrder) { this.ResourceType = ResourceType; this.ResourceName = ResourceName; this.SortOrder = SortOrder; } } |
创建另一个静态类,该类将为GetString和GetStrings提供扩展方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | public static class EnumHelper { public static string GetString(this Enum value) { EnumResourceAttribute ea = (EnumResourceAttribute)value.GetType().GetField(value.ToString()) .GetCustomAttributes(typeof(EnumResourceAttribute), false) .FirstOrDefault(); if (ea != null) { PropertyInfo pi = ea.ResourceType .GetProperty(CommonConstants.ResourceManager); if (pi != null) { ResourceManager rm = (ResourceManager)pi .GetValue(null, null); return rm.GetString(ea.ResourceName); } } return string.Empty; } public static IList GetStrings(this Type enumType) { List<string> stringList = new List<string>(); FieldInfo[] fiArray = enumType.GetFields(); foreach (FieldInfo fi in fiArray) { EnumResourceAttribute ea = (EnumResourceAttribute)fi .GetCustomAttributes(typeof(EnumResourceAttribute), false) .FirstOrDefault(); if (ea != null) { PropertyInfo pi = ea.ResourceType .GetProperty(CommonConstants.ResourceManager); if (pi != null) { ResourceManager rm = (ResourceManager)pi .GetValue(null, null); stringList.Add(rm.GetString(ea.ResourceName)); } } } return stringList.ToList(); } } |
在枚举的元素上,可以编写:
1 2 3 4 5 6 7 |
其中resources.resourceNames.adviceCreateAdviceExternalPriorityMemberHigh&;resources.resourceNames.adviceCreateAdviceExternalPriorityMemberRoutine是资源文件中的常量,也可以说其值可以在不同的区域性中使用。
如果要在MVC体系结构中实现Web应用程序,请创建一个属性
1 2 3 4 5 6 7 8 9 | private IList result; public IList Result { get { result = typeof(Priority).GetStrings(); return result; } } |
在.cshtml文件中,您可以将枚举绑定到DropDownList,如下所示:
1 |
谢谢拉特涅什
使用object enum.parse(system.type enum type,string value,bool ignorecase);从http://blogs.msdn.com/b/tims/archive/2004/04/02/106310.aspx获取
我和哈维在一起,但不要用警察。我可以混合和匹配字符串,int,随便什么。
1 2 3 4 5 6 7 8 9 10 | public class xlsLayout { public int xlHeaderRow = 1; public int xlFirstDataRow = 2; public int xlSkipLinesBetweenFiles = 1; //so 0 would mean don't skip public string xlFileColumn ="A"; public string xlFieldColumn ="B"; public string xlFreindlyNameColumn ="C"; public string xlHelpTextColumn ="D"; } |
后来…
1 2 3 4 5 6 7 8 9 | public partial class Form1 : Form { xlsLayout xlLayout = new xlsLayout(); xl.SetCell(xlLayout.xlFileColumn, xlLayout.xlHeaderRow,"File Name"); xl.SetCell(xlLayout.xlFieldColumn, xlLayout.xlHeaderRow,"Code field name"); xl.SetCell(xlLayout.xlFreindlyNameColumn, xlLayout.xlHeaderRow,"Freindly name"); xl.SetCell(xlLayout.xlHelpTextColumn, xlLayout.xlHeaderRow,"Inline Help Text"); } |
1 2 3 |
输出是:
"形式"
"Windows身份验证"
"单音素"
对于@user29964的答案(这是迄今为止最简单和最接近枚举的答案),我的答案是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | public class StringValue : System.Attribute { private string _value; public StringValue(string value) { _value = value; } public string Value { get { return _value; } } public static string GetStringValue(Enum Flagvalue) { Type type = Flagvalue.GetType(); string[] flags = Flagvalue.ToString().Split(',').Select(x => x.Trim()).ToArray(); List<string> values = new List<string>(); for (int i = 0; i < flags.Length; i++) { FieldInfo fi = type.GetField(flags[i].ToString()); StringValue[] attrs = fi.GetCustomAttributes(typeof(StringValue), false) as StringValue[]; if (attrs.Length > 0) { values.Add(attrs[0].Value); } } return String.Join(",", values); } |
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | [Flags] public enum CompeteMetric { /// <summary> /// u /// </summary> [StringValue("u")]//Json mapping Basic_UniqueVisitors = 1 //Basic , /// <summary> /// vi /// </summary> [StringValue("vi")]//json mapping Basic_Visits = 2// Basic , /// <summary> /// rank /// </summary> [StringValue("rank")]//json mapping Basic_Rank = 4//Basic } |
例子
1 2 | CompeteMetric metrics = CompeteMetric.Basic_Visits | CompeteMetric.Basic_Rank; string strmetrics = StringValue.GetStringValue(metrics); |
这个会回来的"vi,排名"
我非常清楚这个问题已经被回答了,并且OP已经对被接受的答案感到满意了。但我发现大多数答案,包括被接受的答案,都有点复杂。
我有一个项目,给了我这样的情况,我能够做到这一点。
首先,必须考虑枚举名称的大小写:
1 2 3 4 5 6 | public enum AuthenticationMethod { Forms = 1, WindowsAuthentication = 2, SingleSignOn = 3 } |
然后,进行扩展:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | using System.Text.RegularExpression; public static class AnExtension { public static string Name(this Enum value) { string strVal = value.ToString(); try { return Regex.Replace(strVal,"([a-z])([A-Z])","$1 $2"); } catch { } return strVal; } } |
通过这种方式,您可以将每个枚举名称转换为字符串表示形式,每个单词之间用空格分隔。前任:
1 2 | AuthenticationMethod am = AuthenticationMethod.WindowsAuthentication; MessageBox.Show(am.Name()); |