사용자 친화적 인 문자열을 가진 Enum ToString


답변:


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

1
@RayL이 링크 된 버전이 Enum에 확장 메소드 만 추가하기 때문에 링크가 좋습니다. 이것이 당신이 이것을 사용하기를 원하는 전부라면 (로 ArgumentException
표시됨)

4
그것은 모든 열거 형에 자체 확장 방법이 필요하다는 것을 의미합니다. 이것은 더 일반적으로 사용되며 더 많은 작업이 필요하지만 성능을 결정하기 전에 "빠른"의 의미를 수량화하고 싶을 것입니다.
Ray Booysen

2
@petar는 작동하지만 친숙한 문자열을 사용자에게 표시하려는 경우에는 작동하지 않습니다. MY_TYPE에는 밑줄이 있으며 사용자 정의 할 수 없습니다.
Ray Booysen

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

3
@pennyrave : 어. 많은 UI 구성 요소가 DisplayNameAttribute 및 DescriptionAttribute를 찾아서 사용할 것으로 예상합니다. 사실, 이제는 이러한 방법과 확장 방법을 사용하여 이러한 값을 쉽게 얻을 수 있습니다.

60
내가이 문제는 지속적으로 이러한 확장 방법을 작성한다는 것입니다. 속성 메커니즘을 사용하면 장식하는 간단한 방법이며 하나의 메소드 만 호출합니다.
Ray Booysen

5
당신이 무슨 뜻인지 확실하지?
Ray Booysen

9
제 생각에는 default사례 구현이 반환 me.ToString()하고 재정의하려는 열거 형 값에 대한 스위치 사례 문 만 제공하는 것이 좋습니다. 귀하의 예에서, 그것들은 모두 다르지만 실제 사용 사례에서는 대부분의 단일 단어 열거 형 값으로 충분하고 다중 단어 열거 형 값에 대한 재정의 만 제공 할 것으로 생각합니다.
Scott

78

어쩌면 누락 된 것이 있지만 Enum.GetName에 어떤 문제가 있습니까?

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

편집 : 사용자 친화적 인 문자열의 경우 .resource를 통해 국제화 / 현지화를 수행해야하며 데코레이터 속성보다 enum 키를 기반으로 고정 키를 사용하는 것이 더 좋습니다.


12
사용자 친화적 인 열거 형이 아닌 열거 형의 리터럴 값을 반환합니다.
보리스 CALLENS

2
oic-대체 값 (장식 속성)이 I18N을 지원하지 않기 때문에이 값을 기반으로 문자열 리소스 라이브러리를 거쳐야하는 꽤 큰 경우가 있습니다.
annakata

1
I18N의 경우 리소스 라이브러리에서 GetDescription () 메서드를 검색하여 번역 된 문자열을 찾은 다음 설명으로 넘어간 다음 리터럴로 대체합니다.
Boris Callens

3
현지화의 리소스 키로 MyEnum.ToString ()의 경우 +1 내가 해왔 던 그 년
jackvsworld

1
@annakata @ l18N에 대한 지원을 포함하도록 속성 메커니즘을 실제로 확장했습니다. 실제로 간단한 변경입니다.
Ray Booysen

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
죄송하지만 도움을 주셔서 감사합니다. 이 사이트는 Q & A 사이트이기 때문에 답변은 질문에 직접 답변을 시도 해야 합니다. 그리고 질문은 구체적으로 " 나는 문자열에서 가치로 다시 갈 필요가 없다 " 말합니다 .
Jesse

8
긍정적 인 비판에 감사드립니다. 사이트를 처음 접하고 문화와 뉘앙스에 대해 배우는 것은 항상 어렵습니다. 새로운 사람들을 똑바로 세운 당신 같은 사람들이있어서 다행입니다. 다시 한 번, 새 사람을 버리지 않아서 감사합니다.
브라이언 리처드슨

6
@Jesse 그리고 4 년 후 누군가 bjrichardson 코드를 발견하게되어 기쁩니다! SO가 Q & A 사이트 일지 모르지만 질문에 대한 답변이 끝난 후에도 문제가 해결 된 것은 아닙니다.
John

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 2012 년

1
예, 그것은 모두 내가 생각하는 방법의 범위에 달려 있습니다. 속성 방식이 더 일반적이지만 솔루션은보다 현지화되어 있습니다. 결국 요구 사항에 관한 것입니다.
보리스 CALLENS

1
원하는 곳에 확장 방법을 넣을 수 있습니다. 당신이 그들을 사용하려는 곳을 참조해야합니다.

예, 그러나 이것은 친숙한 이름을 원하는 새로운 열거 형을 도입 할 때 마다이 하나의 확장 방법을 다시 작성해야 함을 의미합니다. 이것은 또한 모든 응용 프로그램이 다른 모든 응용 프로그램의 친숙한 이름을 가지고 있음을 의미합니다 ...
Boris Callens

13

다른 게시물은 Java입니다. C #에서는 열거 형에 메서드를 넣을 수 없습니다.

다음과 같이하십시오.

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

열거 형 값에 다른 표시 값을 사용하려는 경우 특성 및 반사를 사용할 수 있습니다.


3
toString은 모든 경우에 안전하지는 않습니다. 동일한 값을 가진 여러 항목이있는 열거 형 (예 : 정수 열거 형)은 테스트 된 항목의 키가 아니라 일치하는 첫 번째 값의 키를 반환하므로 Enum.GetName이 선호됩니다
annakata

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
이 의견이 왜 받아 들여지지 않았는지 또는 가장 많이 찬성되지 않았는 지에 대한 신비입니다. 이 답변을 한 단계 더 발전시켜 'My Enum'을 반환하기 전에 대문자 사이에 공백을 추가 할 수 있습니다.
Vix

12
열거 형의 이름이 이미 좋은 경우 확장 방법이 필요하지 않습니다. 기존 ToString () 메소드를 사용하십시오. string result = "Result: " + ee;
John

이것이 가장 좋은 대답이어야합니다. 그것은 어떤 열거 형에도 작동합니다. 매개 변수의 Enum 유형을 사용하는 실제 Enum으로 변경하여 특정 Enum을 사용하여 구현할 수도 있습니다.
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;

업데이트 (2018 년 3 월 9 일)

확장 방법과 첫 번째 기술의 하이브리드.

나는 열거 형이 "그대로"있는 곳 (일반적인 전역 네임 스페이스가 아닌 출처에 가장 가깝게) 정의되는 것을 선호합니다.

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 vote :이 솔루션은 Enum 구문을 유지하고 리플렉션이나 복잡한 코드없이 문제를 우아하게 해결하므로 +1이됩니다. 그러나 Enums 자체의 기능이 손실됩니다. 따라서 IMO는 좋은 옵션이지만 실제 질문에 대답하지 않고 -1을 얻습니다. 인터넷 0. 죄송합니다. 그래서 더 잘 녹음 할 수있는 방법이 없습니다.
TonyG

@TonyG 박람회. pluarlsight.com의 .net 기술 평가에 대한 몇 가지 질문을 놓친 후 C # 열거가 얼마나 심층적인지 깨달았으므로 적용 할 방법론 (특히 광범위한 사용, 리팩토링)을 결정하기 전에 최소한 그 기능을 알고있는 것이 좋습니다. 약간의 시간이 될 수 있습니다.).
samis

7

Humanize Enums 가능성 과 함께 Humanizer 패키지를 사용할 수 있습니다 . 일축 :

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)

리플렉션도 사용하며 캐시되지 않습니다. 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 ()? 어떤 설명입니까? 골재?
레이 부이 센

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 February

참고로 C # 코드 규칙은 소문자 초기 문자가있는 지역 변수 및 메서드 매개 변수를 원합니다. 웹의 여러 예제에서 this호출 This되는 것을 볼 수있는 확장 메소드 의 매개 변수 는 예외입니다 . 당신이 ( Enum Enum) 와 같은 유형으로 그것을 호출 하면 코드를 읽을 수 없게 만듭니다.
Massimiliano Kraus

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

기본 사항 : V1, V2 및 V3의 3 가지 값을 가진 EnumType이라는 열거 형. "마법"은 Sub Main ()의 Console.WriteLine 호출에서 발생하며, 마지막 인수는 단순히 v.Description입니다. V1의 경우 "One", V2의 경우 "V2", V3의 경우 "Three"를 반환합니다. 이 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 #은 확장 프로그램과 같은 새로운 주제에 대해 녹슨 것입니다)


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

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


1

이것은 일반적인 GetCustomAttributes 메서드와 LINQ를 사용하여 일을 좀 더 깔끔하게 만드는 Ray Booysen 코드에 대한 업데이트입니다.

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

왜 그것이 일반이어야하는지 알지 못하는가? 리플렉션을 사용한다면?
리 루비 에르

@LeeLouviere 구조체 (값 형식)가 매개 변수로 전달 될 때 주로 권투를 피하기 위해.
Richard Anthony Hein

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 }

일반 클래스 :

참고 : 일반 클래스는 열거 형 으로 제한 할 수 없으므로 대신 구조체로 제한 하고 생성자에서 열거 형 을 확인합니다 .

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 년 전 누군가가
Steven이

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.