带有用户友好字符串的Enum ToString


Answers:


350

我使用DescriptionSystem.ComponentModel命名空间中的属性。只需装饰枚举:

private enum PublishStatusValue
{
    [Description("Not Completed")]
    NotCompleted,
    Completed,
    Error
};

然后使用以下代码进行检索:

public static string GetDescription<T>(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();
}

12
这个例子更容易阅读。 stackoverflow.com/questions/1415140/...
RayLoveless

31
我怀疑使用此解决方案中所述的反射会严重影响性能。使用ToFriendlyString扩展方法的Will方法的代码更容易理解,并且其性能也应该非常快。
humbads 2014年

1
我喜欢@RayL链接的版本,因为它只会将扩展方法添加到Enums中。如果这是你想用这个(与指示的ArgumentException,则没有理由有方法是完全通用的。
krillgar

4
这确实意味着每个枚举都需要它自己的扩展方法。这是更一般的用法,并且确实需要更多的工作,但是您可能想要在决定性能之前量化“快速”的含义。
Ray Booysen

2
@petar有效,但如果您希望向用户显示友好字符串则无效。MY_TYPE将带有下划线,并且不可自定义。
雷·布伊森

354

我用扩展方法做到这一点:

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!";
    }
  }
}

6
这比“属性”答案干净得多。真好!
pennyrave 2012年

3
@pennyrave:嗯。许多UI组件都希望找到并使用DisplayNameAttribute和DescriptionAttribute。实际上,现在,我使用这些和扩展方法来轻松获取这些值。

60
我看到的问题是您正在不断编写这些扩展方法。使用属性机制,这是装饰它并且仅调用一个方法的一种简单方法。
Ray Booysen 2014年

5
不明白你的意思?
Ray Booysen 2014年

9
在我看来,最好允许default案例实现返回me.ToString()并且只为要覆盖的枚举值提供switch case语句。在您的示例中,我发现它们都是不同的,但在实际使用案例中,我怀疑大多数单个单词的枚举值就足够了,而您只会为多单词的枚举值提供替代。
斯科特,

78

也许我缺少了一些东西,但是Enum.GetName怎么了?

public string GetName(PublishStatusses value)
{
    return Enum.GetName(typeof(PublishStatusses), value)
}

编辑:对于用户友好的字符串,您需要通过.resource来完成国际化/本地化,并且可以说,最好使用基于枚举键的固定键而不是基于装饰键属性的固定键。


11
我返回枚举的文字值,而不是一些用户友好的值。
鲍里斯·卡伦斯

2
oic-好吧,那么您必须根据该值通过字符串资源库,因为替代项(装饰器属性)将不支持I18N
annakata

1
在I18N的情况下,我将使GetDescription()方法在资源库中搜索已翻译的字符串,然后返回描述,然后返回原义。
鲍里斯·

3
为MyEnum.ToString()+1作为本地化的资源键。我已经这样做了多年
jackvsworld 2013年

1
@annakata我们实际上已经扩展了属性机制,以包括对l18N的支持,实际上这是一个简单的更改。
Ray Booysen 2014年

23

我创建了一个反向扩展方法,将描述转换回枚举值:

public static T ToEnumValue<T>(this string enumerationDescription) where T : struct
{
    var type = typeof(T);

    if (!type.IsEnum)
        throw new ArgumentException("ToEnumValue<T>(): Must be of enum type", "T");

    foreach (object val in System.Enum.GetValues(type))
        if (val.GetDescription<T>() == enumerationDescription)
            return (T)val;

    throw new ArgumentException("ToEnumValue<T>(): Invalid description for enum " + type.Name, "enumerationDescription");
}

15
抱歉,感谢您的帮助!尽管因为这是一个问答站点,所以答案应该是尝试直接回答问题。问题特别指出:“ 我不需要再次从字符串变成值。 ”再次感谢!
杰西

8
感谢您的积极批评。始终很难成为网站的新手并了解其文化和细微差别。我很高兴有像您这样的人将这些新人弄得一团糟。再次感谢您不要丢下新人。
Brian理查森

6
@Jesse 4年后,有人很高兴在这里找到bjrichardson代码!SO可能是一个Q&A站点,但这并不意味着问题在回答后就消失了。
约翰·

18

这里最简单的解决方案是使用自定义扩展方法(至少在.NET 3.5中-您可以将其转换为早期框架版本的静态辅助方法)。

public static string ToCustomString(this PublishStatusses value)
{
    switch(value)
    {
        // Return string depending on value.
    }
    return null;
}

我在这里假设您想返回的不是枚举值的实际名称(您可以通过简单地调用ToString来获得)。


虽然有效,但我更喜欢属性方式。这样,我可以把我的toString方法在一个单独的图书馆,而把自定义字符串表示与枚举本身
鲍里斯Callens

1
很公平。我想此方法的一个优点是,您可以在方法中包含一个参数,以指定一些状态变量,然后根据此参数更改返回的字符串表示形式。
Noldorin

1
是的,这全都取决于我猜方法的范围。尽管“属性”方式更为通用,但您的解决方案却更加本地化。最终,所有这些都与需求有关。
鲍里斯·卡伦斯

1
您可以将扩展方法放在所需的任何位置。您只需要在要使用它们的地方引用它即可。

是的,但这意味着每次您引入一个要为其命名的新枚举时,都应重写此扩展方法。这也意味着您的所有应用程序都将带有所有其他应用程序的友好名称...
Boris Callens

13

另一篇文章是Java。您不能在C#中的Enums中放置方法。

只是做这样的事情:

PublishStatusses status = ...
String s = status.ToString();

如果要为枚举值使用不同的显示值,则可以使用“属性”和“反射”。


3
toString在所有情况下都不安全-具有多个具有相同值的条目的枚举(例如整数枚举)将返回第一个匹配值的键,而不是测试项的键,这就是为什么首选Enum.GetName的原因
annakata 09年

4
对于他的特定枚举,这是最简单的解决方案
-Lemmy

9

最简单的方法是将扩展类包括到您的项目中,它将与项目中的任何枚举一起使用:

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());

2
关于为什么此评论不被接受或最受欢迎的原因,这是一个谜。您可以更进一步,并允许在返回“我的枚举”之前在大写字母之间添加空格。
Vix

12
如果枚举已经很好地命名,则不需要任何扩展方法。只需使用现有的ToString()方法即可。string result = "Result: " + ee;
约翰

这应该是最好的答案。它适用于任何枚举。您甚至可以通过将参数的枚举类型更改为使用该枚举的实际枚举来使用特定的枚举来实现它。
Juanu Haedo

6
该答案和所有注释都忽略了原始请求以提供扩展描述。你们完全错过了返回默认ToString值以外的内容的练习。在这里,我不会对这个答案的所有注解投下反对票,但我确实想这么做。
TonyG

8

其他一些避免类/引用类型的原始选项:

  • 数组方法
  • 嵌套结构方法

数组方法

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];

嵌套结构方法

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<string, string> _fieldUnit;

        public RecordView()
        {
            _fieldUnit.List = new IdValueList<string, string>
            {            
                new ListItem<string>((int)RecordVM.Enum.Id.Minutes, RecordVM.Enum.Id.Minutes.Name()),
                new ListItem<string>((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数组),因为最好将名称字符串来自资源(即配置文件或DB)而不是硬编码,并且因为最终将扩展方法放在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<string, string> _fieldUnit

        public RecordView()
        {
            _fieldUnit.List = new IdValueList<string, string>
            {            
                new ListItem<string>((int)RecordVM.Enum.Id.Minutes, RecordVM.Enum.Id.Minutes.Name()),
                new ListItem<string>((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;
        }
    }
}

+ 1-1 = 0投票:此解决方案保留了Enum语法,并且确实解决了问题,没有反射或复杂的代码,因此在此处+1。但是它失去了枚举本身的功能。因此,尽管IMO这是一个不错的选择,但它无法回答实际问题并得到-1。Net0。很抱歉,我们没有办法更好地记录SO。
TonyG

@TonyG足够公平。在对pluarlsight.com的.net技能评估遗漏了几个问题之后,我开始意识到C#枚举的深度,因此在决定采用哪种方法(尤其是普遍使用,重构)之前,至少了解它们的功能可能是一个好主意。可能会有点时间;)。
samis

7

您可以将Humanizer软件包与Humanize Enums一起使用。一个例子:

enum PublishStatusses
{
    [Description("Custom description")]
    NotCompleted,
    AlmostCompleted,
    Error
};

那么您可以Humanize直接对enum 使用扩展方法:

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)

它也使用反射并且不被缓存。github.com/Humanizr/Humanizer/blob/…–
Konrad,

这将与Ray
Konrad

5

关于Ray Booysen,代码中存在一个错误:带有用户友好字符串的Enum ToString

您需要考虑枚举值的多个属性。

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 && 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();

4
故意省略多个Description属性的检查。如果枚举有两个,并且您习惯使用它来生成描述,则我想认为这是一种特殊情况。我认为实际的错误是我不执行Single()引发异常。否则,整个方法签名就没有意义。GetDescription()?哪个说明?汇总?
Ray Booysen 2011年

4
public enum MyEnum
{
    [Description("Option One")]
    Option_One
}

public static string ToDescriptionString(this Enum This)
{
    Type type = This.GetType();

    string name = Enum.GetName(type, This);

    MemberInfo member = type.GetMembers()
        .Where(w => w.Name == name)
        .FirstOrDefault();

    DescriptionAttribute attribute = member != null
        ? member.GetCustomAttributes(true)
            .Where(w => w.GetType() == typeof(DescriptionAttribute))
            .FirstOrDefault() as DescriptionAttribute
        : null;

    return attribute != null ? attribute.Description : name;
}

3
编写一些文本来解释为什么这应该起作用以及为什么OP不起作用总是很高兴的。
phaberest

仅供参考,C#代码约定希望使用小写首字母的局部变量和方法参数。this扩展方法中的参数是一个例外,您可以This在网上的许多示例中看到该参数。像调用(Enum Enum)一样调用它的类型会降低代码的可读性。
Massimiliano Kraus's

4

代替使用枚举,而是使用静态类。

更换

private enum PublishStatuses{
    NotCompleted,
    Completed,
    Error
};

private static class PublishStatuses{
    public static readonly string NotCompleted = "Not Completed";
    public static readonly string Completed = "Completed";
    public static readonly string Error = "Error";
};

它将像这样使用

PublishStatuses.NotCompleted; // "Not Completed"

使用最常见的“扩展方法”解决方案发布:

私有枚举通常在另一个类中使用。扩展方法解决方案在那里无效,因为它必须在自己的类中。该解决方案可以是私有的,也可以嵌入另一个类中。


2

我碰巧是VB.NET迷,所以这是我的版本,将DescriptionAttribute方法与扩展方法结合在一起。一,结果:

Imports System.ComponentModel ' For <Description>

Module Module1
  ''' <summary>
  ''' An Enum type with three values and descriptions
  ''' </summary>
  Public Enum EnumType
    <Description("One")>
    V1 = 1

    ' This one has no description
    V2 = 2

    <Description("Three")>
    V3 = 3
  End Enum

  Sub Main()
    ' Description method is an extension in EnumExtensions
    For Each v As EnumType In [Enum].GetValues(GetType(EnumType))
      Console.WriteLine("Enum {0} has value {1} and description {2}",
        v,
        CInt(v),
        v.Description
      )
    Next
    ' Output:
    ' Enum V1 has value 1 and description One
    ' Enum V2 has value 2 and description V2
    ' Enum V3 has value 3 and description Three
  End Sub
End Module

基本内容:一个名为EnumType的枚举,具有三个值V1,V2和V3。“魔术”发生在Sub Main()的Console.WriteLine调用中,其中最后一个参数为simple v.Description。对于V1,这将返回“一个”,对于V2,将返回“ V2”,对于V3,将返回“三”。这个Description-method实际上是扩展方法,在另一个名为EnumExtensions的模块中定义:

Option Strict On
Option Explicit On
Option Infer Off

Imports System.Runtime.CompilerServices
Imports System.Reflection
Imports System.ComponentModel

Module EnumExtensions
  Private _Descriptions As New Dictionary(Of String, String)

  ''' <summary>
  ''' This extension method adds a Description method
  ''' to all enum members. The result of the method is the
  ''' value of the Description attribute if present, else
  ''' the normal ToString() representation of the enum value.
  ''' </summary>
  <Extension>
  Public Function Description(e As [Enum]) As String
    ' Get the type of the enum
    Dim enumType As Type = e.GetType()
    ' Get the name of the enum value
    Dim name As String = e.ToString()

    ' Construct a full name for this enum value
    Dim fullName As String = enumType.FullName + "." + name

    ' See if we have looked it up earlier
    Dim enumDescription As String = Nothing
    If _Descriptions.TryGetValue(fullName, enumDescription) Then
      ' Yes we have - return previous value
      Return enumDescription
    End If

    ' Find the value of the Description attribute on this enum value
    Dim members As MemberInfo() = enumType.GetMember(name)
    If members IsNot Nothing AndAlso members.Length > 0 Then
      Dim descriptions() As Object = members(0).GetCustomAttributes(GetType(DescriptionAttribute), False)
      If descriptions IsNot Nothing AndAlso descriptions.Length > 0 Then
        ' Set name to description found
        name = DirectCast(descriptions(0), DescriptionAttribute).Description
      End If
    End If

    ' Save the name in the dictionary:
    _Descriptions.Add(fullName, name)

    ' Return the name
    Return name
  End Function
End Module

由于使用Reflection查找属性的速度很慢,因此查找也将缓存在private中Dictionary,该属性按需填充。

(对VB.NET解决方案很抱歉-将其转换为C#应该相对容易,而我的C#对于诸如扩展之类的新主题也很生疏)


2

用示例干净地总结上述建议:

namespace EnumExtensions {

using System;
using System.Reflection;

public class TextAttribute : Attribute {
   public string Text;
   public TextAttribute( string text ) {
      Text = text;
   }//ctor
}// class TextAttribute

public static class EnumExtender {

public static string ToText( this Enum enumeration ) {

   MemberInfo[] memberInfo = enumeration.GetType().GetMember( enumeration.ToString() );

   if ( memberInfo != null && memberInfo.Length > 0 ) {

      object[] attributes = memberInfo[ 0 ].GetCustomAttributes( typeof(TextAttribute),  false );

      if ( attributes != null && attributes.Length > 0 ) {
         return ( (TextAttribute)attributes[ 0 ] ).Text;
      }

   }//if

   return enumeration.ToString();

}//ToText

}//class EnumExtender

}//namespace

用法:

using System;
using EnumExtensions;

class Program {

public enum Appearance {

  [Text( "left-handed" ) ]
  Left,

  [Text( "right-handed" ) ]
  Right,

}//enum

static void Main( string[] args ) {

   var appearance = Appearance.Left;
   Console.WriteLine( appearance.ToText() );

}//Main

}//class

1
C#中有一个[Description(“”))]属性,为什么不使用它呢?
Stefan Koenen

当然,使用[Description(“”)]是一种方法。但是我希望样本完整。
下划线

2

使用Enum.GetName

从上面的链接...

using System;

public class GetNameTest {
    enum Colors { Red, Green, Blue, Yellow };
    enum Styles { Plaid, Striped, Tartan, Corduroy };

    public static void Main() {

        Console.WriteLine("The 4th value of the Colors Enum is {0}", Enum.GetName(typeof(Colors), 3));
        Console.WriteLine("The 4th value of the Styles Enum is {0}", Enum.GetName(typeof(Styles), 3));
    }
}
// The example displays the following output:
//       The 4th value of the Colors Enum is Yellow
//       The 4th value of the Styles Enum is Corduroy


1

这是对Ray Booysen代码的更新,该代码使用通用的GetCustomAttributes方法和LINQ使事情变得更整洁。

    /// <summary>
    /// Gets the value of the <see cref="T:System.ComponentModel.DescriptionAttribute"/> on an struct, including enums.  
    /// </summary>
    /// <typeparam name="T">The type of the struct.</typeparam>
    /// <param name="enumerationValue">A value of type <see cref="T:System.Enum"/></param>
    /// <returns>If the struct has a Description attribute, this method returns the description.  Otherwise it just calls ToString() on the struct.</returns>
    /// <remarks>Based on http://stackoverflow.com/questions/479410/enum-tostring/479417#479417, but useful for any struct.</remarks>
    public static string GetDescription<T>(this T enumerationValue) where T : struct
    {
        return enumerationValue.GetType().GetMember(enumerationValue.ToString())
                .SelectMany(mi => mi.GetCustomAttributes<DescriptionAttribute>(false),
                    (mi, ca) => ca.Description)
                .FirstOrDefault() ?? enumerationValue.ToString();
    }   

无法看到为什么需要通用吗?如果要使用反射?
Lee Louviere 2013年

@LeeLouviere主要是在将结构(值类型)作为参数传递时避免装箱。
理查德·安东尼·海因

1
而是使用numerationValue.GetType()使用:typeof(T)。
斯拉瓦(Slava)

1
与已接受的答案相比,单行改进很大,而(YMMV)不会降低可读性。是的,使用typeof(T)。
TonyG

1

更简洁的摘要:

using System;
using System.Reflection;

public class TextAttribute : Attribute
{
    public string Text;
    public TextAttribute(string text)
    {
        Text = text;
    }
}  

public static class EnumExtender
{
    public static string ToText(this Enum enumeration)
    {
        var memberInfo = enumeration.GetType().GetMember(enumeration.ToString());
        if (memberInfo.Length <= 0) return enumeration.ToString();

        var attributes = memberInfo[0].GetCustomAttributes(typeof(TextAttribute), false);
        return attributes.Length > 0 ? ((TextAttribute)attributes[0]).Text : enumeration.ToString();
    }
}

下划线描述的用法相同。


0

对于标志枚举包括。

    public static string Description(this Enum value)
    {
        Type type = value.GetType();

        List<string> res = new List<string>();
        var arrValue = value.ToString().Split(',').Select(v=>v.Trim());
        foreach (string strValue in arrValue)
        {
            MemberInfo[] memberInfo = type.GetMember(strValue);
            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)
                {
                    res.Add(((DescriptionAttribute)attrs.Where(t => t.GetType() == typeof(DescriptionAttribute)).FirstOrDefault()).Description);
                }
                else
                    res.Add(strValue);
            }
            else
                res.Add(strValue);
        }

        return res.Aggregate((s,v)=>s+", "+v);
    }

0

如果您只想在单词之间添加空格,则只需

string res = Regex.Replace(PublishStatusses.NotCompleted, "[A-Z]", " $0").Trim();

0

我使用一个通用类来存储枚举/描述对,并使用一个嵌套的帮助器类来获取描述。

枚举

enum Status { Success, Fail, Pending }

通用类:

注意:由于泛型类不能被枚举约束,所以我改为由struct约束,并在构造函数中检查枚举

public class EnumX<T> where T : struct
{
    public T Code { get; set; }
    public string Description { get; set; }

    public EnumX(T code, string desc)
    {
        if (!typeof(T).IsEnum) throw new NotImplementedException();

        Code = code;
        Description = desc;
    }

    public class Helper
    {
        private List<EnumX<T>> codes;

        public Helper(List<EnumX<T>> codes)
        {
            this.codes = codes;
        }

        public string GetDescription(T code)
        {
            EnumX<T> e = codes.Where(c => c.Code.Equals(code)).FirstOrDefault();
            return e is null ? "Undefined" : e.Description;
        }
    }
}

用法:

EnumX<Status>.Helper StatusCodes = new EnumX<Status>.Helper(new List<EnumX<Status>>()
        {
            new EnumX<Status>(Status.Success,"Operation was successful"),
            new EnumX<Status>(Status.Fail,"Operation failed"),
            new EnumX<Status>(Status.Pending,"Operation not complete. Please wait...")
        });

        Console.WriteLine(StatusCodes.GetDescription(Status.Pending));

-2

我认为解决问题的最好(也是最简单)的方法是为您的枚举编写一个扩展方法:

public static string GetUserFriendlyString(this PublishStatusses status)
    {

    }

1
有人早7年前就说过
史蒂文

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.