使用用户友好的字符串枚举ToString

时间:2009-01-26 10:58:39

标签: c# enums tostring

我的枚举包含以下值:

private enum PublishStatusses{
    NotCompleted,
    Completed,
    Error
};

我希望能够以用户友好的方式输出这些值 我不需要能够再次从字符串变为值。

24 个答案:

答案 0 :(得分:319)

我使用扩展方法执行此操作:

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

答案 1 :(得分:318)

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

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

答案 2 :(得分:63)

也许我错过了什么,但是Enum.GetName出了什么问题?

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

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

答案 3 :(得分:18)

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

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

答案 4 :(得分:17)

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

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

我在这里假设您想要返回除枚举值的实际名称之外的其他内容(只需调用ToString即可获得)。

答案 5 :(得分:12)

另一篇文章是Java。你不能在C#中将方法放在枚举中。

做这样的事情:

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

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

答案 6 :(得分: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)" };
        }
    }
}

扩展方法似乎适用于公共区域,而enum的“本地化”定义现在使扩展方法更加冗长。

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

答案 7 :(得分:8)

最简单的方法就是将此扩展类包含在项目中,它将与项目中的任何枚举一起使用:

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

答案 8 :(得分:6)

您可以使用Humanizer包与Humanize Enums可能性。一个例子:

menu-button

然后您可以直接在枚举上使用enum PublishStatusses { [Description("Custom description")] NotCompleted, AlmostCompleted, Error }; 扩展方法:

Humanize

答案 9 :(得分:5)

关于Ray Booysen,代码中有一个错误:Enum ToString with user friendly strings

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

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

答案 10 :(得分:4)

而不是使用枚举使用静态类。

替换

<!doctype html>

<html lang="en">

<head>
  <title>AB</title>
  <link href="styles/intro.css" rel="stylesheet" type="text/css" />
  <meta charset="utf-8">

  <link href="welcome.html" rel="alternate" hreflang="en" />
  <link href="welcome_pt.html" rel="alternate" hreflang="pt" />
</head>

<body id="welcome">

  <a href="home.html" class="button buy" hreflang="en">
    <div>Buy</div>
  </a>

  <a href="apply.html" class="button sell" hreflang="en">
    <div>Sell</div>
  </a>

  <div id="background-div"></div>

  <div id="background2-div"></div>

  <video autoplay muted loop id="videoback">
			<source src="videos/blessings.mp4" type="video/mp4">
		</video>


  <footer>
    <div>
      <nav>
        <ul>
          <li>
            <a href="about.html" hreflang="en">About</a>
          </li>
          <li>
            <a href="contact.html" hreflang="en">Contact</a>
          </li>
        </ul>
      </nav>
    </div>
  </footer>
  <!-- Scripts -->
</body>

</html>

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

使用top&#34;扩展方法问题&#34;解决方案:

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

答案 11 :(得分:4)

sourcestr

答案 12 :(得分: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

答案 13 :(得分:2)

根据本文档:https://docs.microsoft.com/pt-br/dotnet/api/system.enum.tostring?view=netframework-4.8

可以使用以下格式将枚举数转换为字符串:

public enum Example
{
    Example1,
    Example2
}

Console.WriteLine(Example.Example1.ToString("g"));

//Outputs: "Example1"

您可以在此链接中查看所有可能的格式:https://docs.microsoft.com/pt-br/dotnet/api/system.string?view=netframework-4.8

答案 14 :(得分: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调用中,其中最后一个参数只是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查找描述属性的速度很慢,因此查询也会缓存在私有Dictionary中,并按需填充。

(对不起VB.NET解决方案 - 将它转换为C#应该相对简单,而且我的C#在扩展等新主题上生锈了)

答案 15 :(得分: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();
    }
}

与下划线描述的用法相同。

答案 16 :(得分: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();
    }   

答案 17 :(得分:1)

使用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

答案 18 :(得分:0)

我参加聚会晚了 7 年 :-) 但我确信这个话题经常被访问。
所以我想在咖啡里加一点糖:

“F”格式字符串说明符怎么样?

PublishStatusses[] ps = Enum.GetValues<PublishStatusses>();
ps.ToList().ForEach(c => Console.Write($"{c:F} "));

不需要任何显式的函数调用。

事实上,甚至不需要任何格式说明符。 在对字符串进行变量赋值的情况下,ToString() 会起作用:

string foo = PublishStatusses.Error.ToString(); // or ToString("F")

如果要在 CamelCase 字符串的单词之间插入空格,则可以使用正则表达式:

Regex.Replace(foo, "(\\B[A-Z])", " $1")

答案 19 :(得分:0)

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

枚举

enum Status { Success, Fail, Pending }

通用类:

注意:由于通用类不能受 enum 约束,因此我受 struct 约束并检查 enum < / em>。

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

答案 20 :(得分:0)

如果您只想在单词之间添加一个空格,就这么简单

final Shader linearGradient = LinearGradient(
      colors: <Color>[
        Color(0xff002fff),
        Color(0xff00f4ff),
      ],
    ).createShader(Rect.fromCircle(center: Offset(200, 0), radius: 150));

答案 21 :(得分:0)

for flag enum包括。

case R.id.multiple_audio_deleting:
     {
     deleteItems(imageItems);
     isDeleted=true;
     mode.finish();
     break;
 }

答案 22 :(得分:-1)

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

public static string GetUserFriendlyString(this PublishStatusses status)
    {

    }

答案 23 :(得分:-3)

如果您想要完全可自定义的内容,请在此处尝试我的解决方案:

http://www.kevinwilliampang.com/post/Mapping-Enums-To-Strings-and-Strings-to-Enums-in-NET.aspx

基本上,帖子概述了如何将描述属性附加到每个枚举,并提供了从枚举到描述的通用方法。