C# 使用用户友好的字符串枚举 ToString
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/479410/
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
Enum ToString with user friendly strings
提问by Boris Callens
My enum consists of the following values:
我的枚举包含以下值:
private enum PublishStatusses{
NotCompleted,
Completed,
Error
};
I want to be able to output these values in a user friendly way though.
I don't need to be able to go from string to value again.
不过,我希望能够以用户友好的方式输出这些值。
我不需要能够再次从字符串到值。
采纳答案by Ray Booysen
I use the Description
attribute from the System.ComponentModel namespace. Simply decorate the enum:
我使用Description
System.ComponentModel 命名空间中的属性。简单地装饰枚举:
private enum PublishStatusValue
{
[Description("Not Completed")]
NotCompleted,
Completed,
Error
};
Then use this code to retrieve it:
然后使用此代码来检索它:
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();
}
回答by Kevin Pang
If you want something completely customizable, try out my solution here:
如果您想要完全可定制的东西,请在此处尝试我的解决方案:
http://www.kevinwilliampang.com/post/Mapping-Enums-To-Strings-and-Strings-to-Enums-in-NET.aspx
http://www.kevinwilliampang.com/post/Mapping-Enums-To-Strings-and-Strings-to-Enums-in-NET.aspx
Basically, the post outlines how to attach Description attributes to each of your enums and provides a generic way to map from enum to description.
基本上,这篇文章概述了如何将 Description 属性附加到您的每个枚举,并提供了一种从枚举映射到描述的通用方法。
回答by Lemmy
That other post is Java. You can't put methods in Enums in C#.
另一篇文章是Java。你不能在 C# 的枚举中放置方法。
just do something like this:
只是做这样的事情:
PublishStatusses status = ...
String s = status.ToString();
If you want to use different display values for your enum values, you could use Attributes and Reflection.
如果要为枚举值使用不同的显示值,可以使用属性和反射。
回答by Noldorin
The easiest solution here is to use a custom extension method (in .NET 3.5 at least - you can just convert it into a static helper method for earlier framework versions).
这里最简单的解决方案是使用自定义扩展方法(至少在 .NET 3.5 中 - 您可以将其转换为早期框架版本的静态辅助方法)。
public static string ToCustomString(this PublishStatusses value)
{
switch(value)
{
// Return string depending on value.
}
return null;
}
I am assuming here that you want to return something other than the actual name of the enum value (which you can get by simply calling ToString).
我在这里假设您想要返回枚举值的实际名称以外的其他内容(您只需调用 ToString 即可获得)。
回答by annakata
Maybe I'm missing something, but what's wrong with Enum.GetName?
也许我遗漏了一些东西,但是 Enum.GetName 有什么问题?
public string GetName(PublishStatusses value)
{
return Enum.GetName(typeof(PublishStatusses), value)
}
edit: for user-friendly strings, you need to go through a .resource to get internationalisation/localisation done, and it would arguably be better to use a fixed key based on the enum key than a decorator attribute on the same.
编辑:对于用户友好的字符串,您需要通过 .resource 来完成国际化/本地化,并且可以说使用基于枚举键的固定键比使用相同的装饰器属性更好。
回答by annakata
I do this with extension methods:
我用扩展方法来做到这一点:
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!";
}
}
}
回答by Joel MC
With respect to Ray Booysen, there is a bug in the code: Enum ToString with user friendly strings
关于 Ray Booysen,代码中有一个错误:Enum ToString withuserfriendly strings
You need to account for multiple attributes on the enum values.
您需要考虑枚举值的多个属性。
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();
回答by Richard Anthony Hein
This is an update to Ray Booysen's code that uses the generic GetCustomAttributes method and LINQ to make things a bit tidier.
这是对 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();
}
回答by MarkusT
I happen to be a VB.NET fan, so here's my version, combining the DescriptionAttribute method with an extension method. First, the results:
我碰巧是 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
Basic stuff: an enum called EnumType with three values V1, V2 and V3. The "magic" happens in the Console.WriteLine call in Sub Main(), where the last argument is simply v.Description
. This returns "One" for V1, "V2" for V2, and "Three" for V3. This Description-method is in fact an extension method, defined in another module called EnumExtensions:
基本内容:一个名为 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
Because looking up description attributes using Reflection
is slow, the lookups are also cached in a private Dictionary
, that is populated on demand.
因为使用描述属性Reflection
查找速度很慢,所以查找也缓存在一个 private 中Dictionary
,按需填充。
(Sorry for the VB.NET solution - it should be relatively straighforward to translate it to C#, and my C# is rusty on new subjects like extensions)
(对于 VB.NET 解决方案很抱歉 - 将其转换为 C# 应该相对简单,而我的 C# 在扩展等新主题上很生疏)
回答by bjrichardson
I created a reverse extension method to convert the description back into an enum value:
我创建了一个反向扩展方法来将描述转换回枚举值:
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");
}