我的枚举包含以下值:
private enum PublishStatusses{ NotCompleted, Completed, Error };
我希望能够以用户友好的方式输出这些值.
我不需要能够再次从字符串变为值.
我用扩展方法做到这一点:
public enum ErrorLevel { None, Low, High, SoylentGreen } public static class ErrorLevelExtensions { public static string ToFriendlyString(this ErrorLevel me) { switch(me) { case ErrorLevel.None: return "Everything is OK"; case ErrorLevel.Low: return "SNAFU, if you know what I mean."; case ErrorLevel.High: return "Reaching TARFU levels"; case ErrorLevel.SoylentGreen: return "ITS PEOPLE!!!!"; default: return "Get your damn dirty hands off me you FILTHY APE!"; } } }
我使用Description
System.ComponentModel命名空间中的属性.只需装饰枚举:
private enum PublishStatusValue { [Description("Not Completed")] NotCompleted, Completed, Error };
然后使用此代码检索它:
public static string GetDescription(this T 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(); }
也许我错过了一些东西,但Enum.GetName出了什么问题?
public string GetName(PublishStatusses value) { return Enum.GetName(typeof(PublishStatusses), value) }
编辑:对于用户友好的字符串,您需要通过.resource来完成国际化/本地化,并且使用基于枚举键的固定键而不是相同的装饰器属性可能更好.
我创建了一个反向扩展方法,将描述转换回枚举值:
public static T ToEnumValue(this string enumerationDescription) where T : struct { var type = typeof(T); if (!type.IsEnum) throw new ArgumentException("ToEnumValue (): Must be of enum type", "T"); foreach (object val in System.Enum.GetValues(type)) if (val.GetDescription () == enumerationDescription) return (T)val; throw new ArgumentException("ToEnumValue (): Invalid description for enum " + type.Name, "enumerationDescription"); }
这里最简单的解决方案是使用自定义扩展方法(至少在.NET 3.5中 - 您可以将其转换为早期框架版本的静态帮助方法).
public static string ToCustomString(this PublishStatusses value) { switch(value) { // Return string depending on value. } return null; }
我在这里假设您想要返回除枚举值的实际名称之外的其他内容(您可以通过简单地调用ToString获得).
另一篇文章是Java.您不能在C#中将方法放在枚举中.
做这样的事情:
PublishStatusses status = ... String s = status.ToString();
如果要为枚举值使用不同的显示值,可以使用"属性"和"反射".
最简单的方法就是将此扩展类包含在项目中,它将与项目中的任何枚举一起使用:
public static class EnumExtensions { public static string ToFriendlyString(this Enum code) { return Enum.GetName(code.GetType(), code); } }
用法:
enum ExampleEnum { Demo = 0, Test = 1, Live = 2 }
...
ExampleEnum ee = ExampleEnum.Live; Console.WriteLine(ee.ToFriendlyString());
一些其他更原始的选项可以避免类/引用类型:
数组方法
嵌套的struct方法
数组方法
private struct PublishStatusses { public static string[] Desc = { "Not Completed", "Completed", "Error" }; public enum Id { NotCompleted = 0, Completed, Error }; }
用法
string desc = PublishStatusses.Desc[(int)PublishStatusses.Id.Completed];
嵌套的struct方法
private struct PublishStatusses { public struct NotCompleted { public const int Id = 0; public const string Desc = "Not Completed"; } public struct Completed { public const int Id = 1; public const string Desc = "Completed"; } public struct Error { public const int Id = 2; public const string Desc = "Error"; } }
用法
int id = PublishStatusses.NotCompleted.Id; string desc = PublishStatusses.NotCompleted.Desc;
更新(03/09/2018)
扩展方法与上述第一种技术的混合.
我更喜欢将枚举定义为"属于"(最接近其原始来源而不是某些常见的全局命名空间).
namespace ViewModels { public class RecordVM { //public enum Enum { Minutes, Hours } public struct Enum { public enum Id { Minutes, Hours } public static string[] Name = { "Minute(s)", "Hour(s)" }; } } }
扩展方法似乎适用于公共区域,枚举的"本地化"定义现在使扩展方法更加冗长.
namespace Common { public static class EnumExtensions { public static string Name(this RecordVM.Enum.Id id) { return RecordVM.Enum.Name[(int)id]; } } }
枚举的用法示例及其扩展方法.
namespace Views { public class RecordView { private RecordDataFieldList_fieldUnit; public RecordView() { _fieldUnit.List = new IdValueList { new ListItem ((int)RecordVM.Enum.Id.Minutes, RecordVM.Enum.Id.Minutes.Name()), new ListItem ((int)RecordVM.Enum.Id.Hours, RecordVM.Enum.Id.Hours.Name()) }; } private void Update() { RecordVM.Enum.Id eId = DetermineUnit(); _fieldUnit.Input.Text = _fieldUnit.List.SetSelected((int)eId).Value; } } }
注意:我实际上决定消除Enum
包装器(和Name
数组),因为名称字符串最好来自资源(即配置文件或数据库)而不是硬编码,因为我最终将扩展方法放在ViewModels
命名空间(只是在另一个"CommonVM.cs"文件中).此外,整个.Id
事情变得分散注意力和繁琐.
namespace ViewModels { public class RecordVM { public enum Enum { Minutes, Hours } //public struct Enum //{ // public enum Id { Minutes, Hours } // public static string[] Name = { "Minute(s)", "Hour(s)" }; //} } }
CommonVM.cs
//namespace Common namespace ViewModels { public static class EnumExtensions { public static string Name(this RecordVM.Enum id) { //return RecordVM.Enum.Name[(int)id]; switch (id) { case RecordVM.Enum.Minutes: return "Minute(s)"; case RecordVM.Enum.Hours: return "Hour(s)"; default: return null; } } } }
枚举的用法示例及其扩展方法.
namespace Views { public class RecordView { private RecordDataFieldList_fieldUnit public RecordView() { _fieldUnit.List = new IdValueList { new ListItem ((int)RecordVM.Enum.Id.Minutes, RecordVM.Enum.Id.Minutes.Name()), new ListItem ((int)RecordVM.Enum.Id.Hours, RecordVM.Enum.Id.Hours.Name()) }; } private void Update() { RecordVM.Enum eId = DetermineUnit(); _fieldUnit.Input.Text = _fieldUnit.List.SetSelected((int)eId).Value; } } }
您可以使用Humanizer包和Humanize Enums possiblity.一个例子:
enum PublishStatusses { [Description("Custom description")] NotCompleted, AlmostCompleted, Error };
那么你可以Humanize
直接在枚举上使用扩展方法:
var st1 = PublishStatusses.NotCompleted; var str1 = st1.Humanize(); // will result in Custom description var st2 = PublishStatusses.AlmostCompleted; var str2 = st2.Humanize(); // will result in Almost completed (calculated automaticaly)
关于Ray Booysen,代码中存在一个错误:使用用户友好字符串的Enum ToString
您需要在枚举值上考虑多个属性.
public static string GetDescription(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 && attrs.Where(t => t.GetType() == typeof(DescriptionAttribute)).FirstOrDefault() != null) { //Pull out the description value return ((DescriptionAttribute)attrs.Where(t=>t.GetType() == typeof(DescriptionAttribute)).FirstOrDefault()).Description; } } //If we have no description attribute, just return the ToString of the enum return enumerationValue.ToString();