Enum의 문자열 표현
다음 열거 형이 있습니다.
public enum AuthenticationMethod
{
FORMS = 1,
WINDOWSAUTHENTICATION = 2,
SINGLESIGNON = 3
}
그러나 문제는 ID 1이 아닌 AuthenticationMethod.FORMS를 요청할 때 "FORMS"라는 단어가 필요하다는 것입니다.
이 문제에 대한 다음 해결책을 찾았습니다 ( 링크 ).
먼저 "StringValue"라는 사용자 지정 속성을 만들어야합니다.
public class StringValue : System.Attribute
{
private readonly string _value;
public StringValue(string value)
{
_value = value;
}
public string Value
{
get { return _value; }
}
}
그런 다음이 속성을 열거 자에 추가 할 수 있습니다.
public enum AuthenticationMethod
{
[StringValue("FORMS")]
FORMS = 1,
[StringValue("WINDOWS")]
WINDOWSAUTHENTICATION = 2,
[StringValue("SSO")]
SINGLESIGNON = 3
}
그리고 물론 StringValue를 검색하려면 무언가가 필요합니다.
public static class StringEnum
{
public static string GetStringValue(Enum value)
{
string output = null;
Type type = value.GetType();
//Check first in our cached results...
//Look for our 'StringValueAttribute'
//in the field's custom attributes
FieldInfo fi = type.GetField(value.ToString());
StringValue[] attrs =
fi.GetCustomAttributes(typeof(StringValue),
false) as StringValue[];
if (attrs.Length > 0)
{
output = attrs[0].Value;
}
return output;
}
}
이제 열거 자에 대한 문자열 값을 얻을 수있는 도구가 있습니다. 그런 다음 다음과 같이 사용할 수 있습니다.
string valueOfAuthenticationMethod = StringEnum.GetStringValue(AuthenticationMethod.FORMS);
좋아, 이제이 모든 것이 매력처럼 작동하지만 나는 그것이 많은 작업을한다고 생각한다. 이것에 대한 더 나은 해결책이 있는지 궁금합니다.
나는 또한 사전과 정적 속성으로 무언가를 시도했지만 그것도 좋지 않았습니다.
type-safe-enum 패턴을 사용해보십시오 .
public sealed class AuthenticationMethod {
private readonly String name;
private readonly int value;
public static readonly AuthenticationMethod FORMS = new AuthenticationMethod (1, "FORMS");
public static readonly AuthenticationMethod WINDOWSAUTHENTICATION = new AuthenticationMethod (2, "WINDOWS");
public static readonly AuthenticationMethod SINGLESIGNON = new AuthenticationMethod (3, "SSN");
private AuthenticationMethod(int value, String name){
this.name = name;
this.value = value;
}
public override String ToString(){
return name;
}
}
명시 적 (또는 암시 적) 유형 변환 업데이트 는 다음과 같이 수행 할 수 있습니다.
매핑으로 정적 필드 추가
private static readonly Dictionary<string, AuthenticationMethod> instance = new Dictionary<string,AuthenticationMethod>();
- nb 인스턴스 생성자를 호출 할 때 "열거 형 멤버"필드의 초기화로 인해 NullReferenceException이 발생하지 않도록하려면 클래스의 "열거 형 멤버"필드 앞에 사전 필드를 배치해야합니다. 이는 정적 필드 이니셜 라이저가 선언 순서로 호출되고 정적 생성자 이전에 모든 정적 필드가 초기화되기 전과 정적 생성자가 호출되기 전에 인스턴스 생성자가 호출 될 수있는 이상하고 필요하지만 혼란스러운 상황을 만들기 때문입니다.
인스턴스 생성자에이 매핑 채우기
instance[name] = this;
-
public static explicit operator AuthenticationMethod(string str) { AuthenticationMethod result; if (instance.TryGetValue(str, out result)) return result; else throw new InvalidCastException(); }
사용 방법
Enum.GetName(Type MyEnumType, object enumvariable)
( Shipper
정의 된 열거 형 이라고 가정 )
Shipper x = Shipper.FederalExpress;
string s = Enum.GetName(typeof(Shipper), x);
조사 할 가치가있는 Enum 클래스에는 다른 정적 메서드가 많이 있습니다.
ToString ()을 사용하여 값이 아닌 이름을 참조 할 수 있습니다.
Console.WriteLine("Auth method: {0}", AuthenticationMethod.Forms.ToString());
문서는 다음과 같습니다.
http://msdn.microsoft.com/en-us/library/16c1xs4z.aspx
... 그리고 Pascal Case에서 열거 형의 이름을 지정하면 (예 : ThisIsMyEnumValue = 1 등) 매우 간단한 정규식을 사용하여 친숙한 형식을 인쇄 할 수 있습니다.
static string ToFriendlyCase(this string EnumString)
{
return Regex.Replace(EnumString, "(?!^)([A-Z])", " $1");
}
모든 문자열에서 쉽게 호출 할 수 있습니다.
Console.WriteLine("ConvertMyCrazyPascalCaseSentenceToFriendlyCase".ToFriendlyCase());
출력 :
My Crazy Pascal 케이스 문장을 친절한 케이스로 변환
이를 통해 사용자 지정 속성을 만들고 열거 형에 연결하거나 조회 테이블을 사용하여 친숙한 문자열과 열거 형 값을 결합하고 무엇보다도 자체 관리가 가능하며 무한한 파스칼 케이스 문자열에서 사용할 수 있습니다. 더 재사용 가능합니다. 물론 솔루션이 제공하는 열거 형 과 다른 친숙한 이름 을 가질 수는 없습니다 .
그래도 더 복잡한 시나리오에서는 원래 솔루션을 좋아합니다. 솔루션을 한 단계 더 나아가서 GetStringValue를 열거 형의 확장 메서드로 만들면 StringEnum.GetStringValue ...와 같이 참조 할 필요가 없습니다.
public static string GetStringValue(this AuthenticationMethod value)
{
string output = null;
Type type = value.GetType();
FieldInfo fi = type.GetField(value.ToString());
StringValue[] attrs = fi.GetCustomAttributes(typeof(StringValue), false) as StringValue[];
if (attrs.Length > 0)
output = attrs[0].Value;
return output;
}
그런 다음 열거 형 인스턴스에서 직접 쉽게 액세스 할 수 있습니다.
Console.WriteLine(AuthenticationMethod.SSO.GetStringValue());
불행히도 열거 형에 대한 속성을 얻기위한 반영은 매우 느립니다.
이 질문을 참조하십시오 : 누구나 enum 값에 대한 사용자 정의 속성을 얻는 빠른 방법을 알고 있습니까?
는 .ToString()
너무 열거에 매우 느립니다.
하지만 열거 형에 대한 확장 메서드를 작성할 수 있습니다.
public static string GetName( this MyEnum input ) {
switch ( input ) {
case MyEnum.WINDOWSAUTHENTICATION:
return "Windows";
//and so on
}
}
좋지는 않지만 빠르며 속성이나 필드 이름에 대한 반영이 필요하지 않습니다.
C # 6 업데이트
당신은 C # 6을 사용할 수있는 경우 새로운 nameof
운영자는 그래서, 열거 작동 nameof(MyEnum.WINDOWSAUTHENTICATION)
으로 변환됩니다 "WINDOWSAUTHENTICATION"
에 컴파일 시간 이 열거 이름을 얻을 수있는 가장 빠른 방법 만들기.
이것은 명시 적 열거 형을 인라인 상수로 변환하므로 변수에있는 열거 형에는 작동하지 않습니다. 그래서:
nameof(AuthenticationMethod.FORMS) == "FORMS"
그러나...
var myMethod = AuthenticationMethod.FORMS;
nameof(myMethod) == "myMethod"
확장 방법을 사용합니다.
public static class AttributesHelperExtension
{
public static string ToDescription(this Enum value)
{
var da = (DescriptionAttribute[])(value.GetType().GetField(value.ToString())).GetCustomAttributes(typeof(DescriptionAttribute), false);
return da.Length > 0 ? da[0].Description : value.ToString();
}
}
이제 다음으로 장식하십시오 enum
.
public enum AuthenticationMethod
{
[Description("FORMS")]
FORMS = 1,
[Description("WINDOWSAUTHENTICATION")]
WINDOWSAUTHENTICATION = 2,
[Description("SINGLESIGNON ")]
SINGLESIGNON = 3
}
전화 할 때
AuthenticationMethod.FORMS.ToDescription()
당신은 얻을 것이다 "FORMS"
.
ToString()
방법을 사용하십시오.
public enum any{Tomato=0,Melon,Watermelon}
문자열을 참조하려면 다음을 Tomato
사용하십시오.
any.Tomato.ToString();
System.ComponentModel 네임 스페이스의 Description 특성을 사용합니다. 열거 형을 장식 한 다음이 코드를 사용하여 검색합니다.
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)
{
//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();
}
예로서:
public enum Cycle : int
{
[Description("Daily Cycle")]
Daily = 1,
Weekly,
Monthly
}
이 코드는 "Friendly name"이 필요하지 않은 열거 형에 적합하며 열거 형의 .ToString () 만 반환합니다.
.Net 4.0 이상에서 이에 대한 매우 간단한 솔루션입니다. 다른 코드는 필요하지 않습니다.
public enum MyStatus
{
Active = 1,
Archived = 2
}
문자열을 얻으려면 다음을 사용하십시오.
MyStatus.Active.ToString("f");
또는
MyStatus.Archived.ToString("f");`
값은 "Active"또는 "Archived"입니다.
호출 할 때 다른 문자열 형식 (위의 "f")을 Enum.ToString
보려면이 열거 형식 문자열 페이지를 참조하십시오.
나는 Jakub Šturc의 대답을 정말 좋아하지만 스위치-케이스 문과 함께 사용할 수 없다는 단점이 있습니다. 다음은 switch 문과 함께 사용할 수있는 그의 답변의 약간 수정 된 버전입니다.
public sealed class AuthenticationMethod
{
#region This code never needs to change.
private readonly string _name;
public readonly Values Value;
private AuthenticationMethod(Values value, String name){
this._name = name;
this.Value = value;
}
public override String ToString(){
return _name;
}
#endregion
public enum Values
{
Forms = 1,
Windows = 2,
SSN = 3
}
public static readonly AuthenticationMethod FORMS = new AuthenticationMethod (Values.Forms, "FORMS");
public static readonly AuthenticationMethod WINDOWSAUTHENTICATION = new AuthenticationMethod (Values.Windows, "WINDOWS");
public static readonly AuthenticationMethod SINGLESIGNON = new AuthenticationMethod (Values.SSN, "SSN");
}
따라서 Jakub Šturc의 답변의 모든 이점을 얻을 수 있으며 다음과 같은 switch 문과 함께 사용할 수 있습니다.
var authenticationMethodVariable = AuthenticationMethod.FORMS; // Set the "enum" value we want to use.
var methodName = authenticationMethodVariable.ToString(); // Get the user-friendly "name" of the "enum" value.
// Perform logic based on which "enum" value was chosen.
switch (authenticationMethodVariable.Value)
{
case authenticationMethodVariable.Values.Forms: // Do something
break;
case authenticationMethodVariable.Values.Windows: // Do something
break;
case authenticationMethodVariable.Values.SSN: // Do something
break;
}
위의 몇 가지 제안을 일부 캐싱과 결합하여 사용합니다. 이제 인터넷 어딘가에서 찾은 코드에서 아이디어를 얻었지만 어디서 얻었는지 기억하거나 찾을 수 없습니다. 따라서 누군가 유사하게 보이는 것을 발견하면 저작자 표시로 의견을 말하십시오.
어쨌든 사용법에는 유형 변환기가 포함되므로 UI에 바인딩하는 경우 '그냥 작동'합니다. 유형 변환기에서 정적 메소드로 초기화하여 빠른 코드 조회를 위해 Jakub의 패턴으로 확장 할 수 있습니다.
기본 사용량은 다음과 같습니다.
[TypeConverter(typeof(CustomEnumTypeConverter<MyEnum>))]
public enum MyEnum
{
// The custom type converter will use the description attribute
[Description("A custom description")]
ValueWithCustomDescription,
// This will be exposed exactly.
Exact
}
사용자 지정 열거 형 형식 변환기의 코드는 다음과 같습니다.
public class CustomEnumTypeConverter<T> : EnumConverter
where T : struct
{
private static readonly Dictionary<T,string> s_toString =
new Dictionary<T, string>();
private static readonly Dictionary<string, T> s_toValue =
new Dictionary<string, T>();
private static bool s_isInitialized;
static CustomEnumTypeConverter()
{
System.Diagnostics.Debug.Assert(typeof(T).IsEnum,
"The custom enum class must be used with an enum type.");
}
public CustomEnumTypeConverter() : base(typeof(T))
{
if (!s_isInitialized)
{
Initialize();
s_isInitialized = true;
}
}
protected void Initialize()
{
foreach (T item in Enum.GetValues(typeof(T)))
{
string description = GetDescription(item);
s_toString[item] = description;
s_toValue[description] = item;
}
}
private static string GetDescription(T optionValue)
{
var optionDescription = optionValue.ToString();
var optionInfo = typeof(T).GetField(optionDescription);
if (Attribute.IsDefined(optionInfo, typeof(DescriptionAttribute)))
{
var attribute =
(DescriptionAttribute)Attribute.
GetCustomAttribute(optionInfo, typeof(DescriptionAttribute));
return attribute.Description;
}
return optionDescription;
}
public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture,
object value, Type destinationType)
{
var optionValue = (T)value;
if (destinationType == typeof(string) &&
s_toString.ContainsKey(optionValue))
{
return s_toString[optionValue];
}
return base.ConvertTo(context, culture, value, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value)
{
var stringValue = value as string;
if (!string.IsNullOrEmpty(stringValue) && s_toValue.ContainsKey(stringValue))
{
return s_toValue[stringValue];
}
return base.ConvertFrom(context, culture, value);
}
}
}
귀하의 질문에서 열거 형의 숫자 값이 실제로 필요하다고 결코 말하지 않았습니다.
문자열 유형의 열거 형이 필요하지 않고 필요한 경우 (정수 유형이 아니므로 열거 형의 기반이 될 수 없음) 여기에 방법이 있습니다.
static class AuthenticationMethod
{
public static readonly string
FORMS = "Forms",
WINDOWSAUTHENTICATION = "WindowsAuthentication";
}
열거 형과 동일한 구문을 사용하여 참조 할 수 있습니다.
if (bla == AuthenticationMethod.FORMS)
숫자 값 (숫자 대신 문자열 비교)보다 약간 느리지 만 플러스 쪽에서는 문자열에 액세스하기 위해 반사 (느림)를 사용하지 않습니다.
확장 방법으로 이것을 해결하는 방법 :
using System.ComponentModel;
public static string GetDescription(this Enum value)
{
var descriptionAttribute = (DescriptionAttribute)value.GetType()
.GetField(value.ToString())
.GetCustomAttributes(false)
.Where(a => a is DescriptionAttribute)
.FirstOrDefault();
return descriptionAttribute != null ? descriptionAttribute.Description : value.ToString();
}
열거 형 :
public enum OrderType
{
None = 0,
[Description("New Card")]
NewCard = 1,
[Description("Reload")]
Refill = 2
}
사용법 (여기서 o.OrderType은 열거 형과 이름이 같은 속성) :
o.OrderType.GetDescription()
실제 열거 형 값 NewCard 및 Refill 대신 "New Card"또는 "Reload"문자열이 표시됩니다.
업데이트 : 8 년 후 C #을 오랫동안 건드리지 않은이 페이지를 방문하면 내 대답이 더 이상 최상의 솔루션이 아닌 것 같습니다. 속성 함수와 연결된 변환기 솔루션이 정말 마음에 듭니다.
이 글을 읽고 있다면 다른 답변도 확인하십시오.
(힌트 : 이것 위에 있습니다)
대부분의 경우 Jakub Šturc 가 선택한 답변이 정말 마음에 들었지만 코드를 복사하여 붙여 넣는 것을 정말 싫어하고 가능한 한 적게 시도하십시오.
그래서 저는 대부분의 기능이 상속 / 내장 된 EnumBase 클래스를 원했기 때문에 동작 대신 콘텐츠에 집중하도록했습니다.
이 접근 방식의 주요 문제는 Enum 값이 형식에 안전한 인스턴스이지만 상호 작용이 Enum 클래스 형식의 정적 구현과 관련된다는 사실에 기반합니다. 그래서 제네릭 마법의 도움으로 마침내 올바른 조합을 얻은 것 같습니다. 누군가 내가 한 것처럼 유용하다고 생각하기를 바랍니다.
Jakub의 예제부터 시작하지만 상속과 제네릭을 사용합니다.
public sealed class AuthenticationMethod : EnumBase<AuthenticationMethod, int>
{
public static readonly AuthenticationMethod FORMS =
new AuthenticationMethod(1, "FORMS");
public static readonly AuthenticationMethod WINDOWSAUTHENTICATION =
new AuthenticationMethod(2, "WINDOWS");
public static readonly AuthenticationMethod SINGLESIGNON =
new AuthenticationMethod(3, "SSN");
private AuthenticationMethod(int Value, String Name)
: base( Value, Name ) { }
public new static IEnumerable<AuthenticationMethod> All
{ get { return EnumBase<AuthenticationMethod, int>.All; } }
public static explicit operator AuthenticationMethod(string str)
{ return Parse(str); }
}
다음은 기본 클래스입니다.
using System;
using System.Collections.Generic;
using System.Linq; // for the .AsEnumerable() method call
// E is the derived type-safe-enum class
// - this allows all static members to be truly unique to the specific
// derived class
public class EnumBase<E, T> where E: EnumBase<E, T>
{
#region Instance code
public T Value { get; private set; }
public string Name { get; private set; }
protected EnumBase(T EnumValue, string Name)
{
Value = EnumValue;
this.Name = Name;
mapping.Add(Name, this);
}
public override string ToString() { return Name; }
#endregion
#region Static tools
static private readonly Dictionary<string, EnumBase<E, T>> mapping;
static EnumBase() { mapping = new Dictionary<string, EnumBase<E, T>>(); }
protected static E Parse(string name)
{
EnumBase<E, T> result;
if (mapping.TryGetValue(name, out result))
{
return (E)result;
}
throw new InvalidCastException();
}
// This is protected to force the child class to expose it's own static
// method.
// By recreating this static method at the derived class, static
// initialization will be explicit, promising the mapping dictionary
// will never be empty when this method is called.
protected static IEnumerable<E> All
{ get { return mapping.Values.AsEnumerable().Cast<E>(); } }
#endregion
}
Keith에 동의하지만 (아직) 투표 할 수 없습니다.
정적 메서드와 swith 문을 사용하여 원하는 것을 정확하게 반환합니다. 데이터베이스에 tinyint를 저장하고 코드는 실제 열거 형 만 사용하므로 문자열은 UI 요구 사항을위한 것입니다. 수많은 테스트를 거친 결과 최고의 성능과 출력에 대한 대부분의 제어가 이루어졌습니다.
public static string ToSimpleString(this enum)
{
switch (enum)
{
case ComplexForms:
return "ComplexForms";
break;
}
}
public static string ToFormattedString(this enum)
{
switch (enum)
{
case ComplexForms:
return "Complex Forms";
break;
}
}
그러나 일부 계정에서는 이로 인해 유지 관리가 악몽되고 일부 코드 냄새가 발생할 수 있습니다. 길고 많은 열거 형 또는 자주 변경되는 열거 형을 주시하려고합니다. 그렇지 않으면 이것은 저에게 훌륭한 솔루션이었습니다.
간단한 "Enum"을 구현하려고하지만 값이 int 대신 문자열 인 경우 여기에 가장 간단한 솔루션이 있습니다.
public sealed class MetricValueList
{
public static readonly string Brand = "A4082457-D467-E111-98DC-0026B9010912";
public static readonly string Name = "B5B5E167-D467-E111-98DC-0026B9010912";
}
이행:
var someStringVariable = MetricValueList.Brand;
이 문제에 직면했을 때 먼저 답을 찾으려고하는 몇 가지 질문이 있습니다.
- 내 열거 형 값의 이름이 목적에 맞게 충분히 친숙합니까? 아니면 더 친숙한 이름을 제공해야합니까?
- 왕복이 필요한가요? 즉, 텍스트 값을 가져 와서 열거 형 값으로 구문 분석해야합니까?
- 내 프로젝트의 많은 열거 형에 대해 수행해야하는 작업입니까, 아니면 하나만 수행해야합니까?
- 이 정보를 표시 할 UI 요소의 종류는 무엇입니까? 특히 UI에 바인딩하거나 속성 시트를 사용합니까?
- 현지화 할 수 있어야합니까?
이를 수행하는 가장 간단한 방법 Enum.GetValue
은를 사용하는 것입니다 (그리고를 사용하여 라운드 트립을 지원 Enum.Parse
). 또한 TypeConverter
Steve Mitcham이 제안한 것처럼 UI 바인딩을 지원하기 위해. ( TypeConverter
속성 시트를 사용할 때 를 만들 필요는 없습니다. 이는 속성 시트의 좋은 점 중 하나입니다. 주님은 자신의 문제가 있다는 것을 알고 계십니다.)
일반적으로 위의 질문에 대한 답변이 작동하지 않을 것임을 시사하는 경우 다음 단계는 static Dictionary<MyEnum, string>
또는 Dictionary<Type, Dictionary<int, string>>
. 일반적으로 배포 후 친숙한 값을 변경해야하기 때문에 속성을 사용하여 코드를 장식하는 중간 단계를 건너 뛰는 경향이 있습니다.
나는 이것을 아래 인용 된 게시물에 대한 코멘트로 게시하고 싶었지만 충분한 담당자가 없기 때문에 할 수 없었습니다. 그러니 아래로 투표하지 마십시오. 코드에 오류가 포함되어 있으며이 솔루션을 사용하려는 개인에게이를 지적하고 싶었습니다.
[TypeConverter(typeof(CustomEnumTypeConverter(typeof(MyEnum))] public enum MyEnum { // The custom type converter will use the description attribute [Description("A custom description")] ValueWithCustomDescription, // This will be exposed exactly. Exact }
해야한다
[TypeConverter(typeof(CustomEnumTypeConverter<MyEnum>))]
public enum MyEnum
{
// The custom type converter will use the description attribute
[Description("A custom description")]
ValueWithCustomDescription,
// This will be exposed exactly.
Exact
}
Brillant!
내 변형
public struct Colors
{
private String current;
private static string red = "#ff0000";
private static string green = "#00ff00";
private static string blue = "#0000ff";
private static IList<String> possibleColors;
public static Colors Red { get { return (Colors) red; } }
public static Colors Green { get { return (Colors) green; } }
public static Colors Blue { get { return (Colors) blue; } }
static Colors()
{
possibleColors = new List<string>() {red, green, blue};
}
public static explicit operator String(Colors value)
{
return value.current;
}
public static explicit operator Colors(String value)
{
if (!possibleColors.Contains(value))
{
throw new InvalidCastException();
}
Colors color = new Colors();
color.current = value;
return color;
}
public static bool operator ==(Colors left, Colors right)
{
return left.current == right.current;
}
public static bool operator !=(Colors left, Colors right)
{
return left.current != right.current;
}
public bool Equals(Colors other)
{
return Equals(other.current, current);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (obj.GetType() != typeof(Colors)) return false;
return Equals((Colors)obj);
}
public override int GetHashCode()
{
return (current != null ? current.GetHashCode() : 0);
}
public override string ToString()
{
return current;
}
}
코드는 약간 못 생겼지 만이 구조체의 사용법은 매우 현명합니다.
Colors color1 = Colors.Red;
Console.WriteLine(color1); // #ff0000
Colors color2 = (Colors) "#00ff00";
Console.WriteLine(color2); // #00ff00
// Colors color3 = "#0000ff"; // Compilation error
// String color4 = Colors.Red; // Compilation error
Colors color5 = (Colors)"#ff0000";
Console.WriteLine(color1 == color5); // True
Colors color6 = (Colors)"#00ff00";
Console.WriteLine(color1 == color6); // False
또한 이러한 열거 형이 많이 필요한 경우 코드 생성 (예 : T4)이 사용될 수 있다고 생각합니다.
옵션 1:
public sealed class FormsAuth
{
public override string ToString{return "Forms Authtentication";}
}
public sealed class WindowsAuth
{
public override string ToString{return "Windows Authtentication";}
}
public sealed class SsoAuth
{
public override string ToString{return "SSO";}
}
그리고
object auth = new SsoAuth(); //or whatever
//...
//...
// blablabla
DoSomethingWithTheAuth(auth.ToString());
옵션 2 :
public enum AuthenticationMethod
{
FORMS = 1,
WINDOWSAUTHENTICATION = 2,
SINGLESIGNON = 3
}
public class MyClass
{
private Dictionary<AuthenticationMethod, String> map = new Dictionary<AuthenticationMethod, String>();
public MyClass()
{
map.Add(AuthenticationMethod.FORMS,"Forms Authentication");
map.Add(AuthenticationMethod.WINDOWSAUTHENTICATION ,"Windows Authentication");
map.Add(AuthenticationMethod.SINGLESIGNON ,"SSo Authentication");
}
}
우리가 해결하려는 문제에 대해 생각한다면 그것은 우리에게 필요한 열거 형이 아닙니다. 특정 수의 값을 서로 연관시킬 수있는 객체가 필요합니다. 즉, 클래스를 정의합니다.
Jakub Šturc의 type-safe enum 패턴은 내가 여기서 보는 최고의 옵션입니다.
보세요 :
- 개인 생성자가 있으므로 클래스 자체 만 허용 된 값을 정의 할 수 있습니다.
- 봉인 된 클래스이므로 상속을 통해 값을 수정할 수 없습니다.
- 형식이 안전하므로 메서드가 해당 형식 만 요구할 수 있습니다.
- 값에 액세스하여 발생하는 반사 성능 저하가 없습니다.
- 마지막으로 이름, 설명 및 숫자 값과 같이 두 개 이상의 필드를 함께 연결하도록 수정할 수 있습니다.
나를 위해 실용적인 접근 방식은 클래스 내부 클래스입니다.
public class MSEModel
{
class WITS
{
public const string DATE = "5005";
public const string TIME = "5006";
public const string MD = "5008";
public const string ROP = "5075";
public const string WOB = "5073";
public const string RPM = "7001";
...
}
다음은 문자열을 열거 형과 연결하는 작업을 수행하는 또 다른 방법입니다.
struct DATABASE {
public enum enums {NOTCONNECTED, CONNECTED, ERROR}
static List<string> strings =
new List<string>() {"Not Connected", "Connected", "Error"};
public string GetString(DATABASE.enums value) {
return strings[(int)value];
}
}
이 메서드는 다음과 같이 호출됩니다.
public FormMain() {
DATABASE dbEnum;
string enumName = dbEnum.GetString(DATABASE.enums.NOTCONNECTED);
}
관련 열거 형을 자체 구조체로 그룹화 할 수 있습니다. 이 메서드는 열거 형 유형을 사용하므로 Intellisense를 사용하여 GetString()
호출 할 때 열거 형 목록을 표시 할 수 있습니다 .
선택적으로 DATABASE
구조체 에서 new 연산자를 사용할 수 있습니다 . 사용 List
하지 않으면 첫 번째 GetString()
호출이 이루어질 때까지 문자열 이 할당되지 않습니다 .
여기에 많은 훌륭한 답변이 있지만 제 경우에는 "문자열 열거 형"에서 원하는 것을 해결하지 못했습니다.
- switch 문에서 사용 가능 (예 : switch (myEnum))
- 함수 매개 변수 (예 : foo (myEnum type))에서 사용할 수 있습니다.
- 참조 가능 (예 : myEnum.FirstElement)
- 예를 들어 문자열을 사용할 수 있습니다. foo ( "FirstElement") == foo (myEnum.FirstElement)
1,2 & 4는 실제로 문자열의 C # Typedef로 해결할 수 있습니다 (문자열은 C #에서 전환 가능하므로)
3은 정적 const 문자열로 해결할 수 있습니다. 따라서 동일한 요구 사항이있는 경우 가장 간단한 방법입니다.
public sealed class Types
{
private readonly String name;
private Types(String name)
{
this.name = name;
}
public override String ToString()
{
return name;
}
public static implicit operator Types(string str)
{
return new Types(str);
}
public static implicit operator string(Types str)
{
return str.ToString();
}
#region enum
public const string DataType = "Data";
public const string ImageType = "Image";
public const string Folder = "Folder";
#endregion
}
예를 들면 다음과 같습니다.
public TypeArgs(Types SelectedType)
{
Types SelectedType = SelectedType
}
과
public TypeObject CreateType(Types type)
{
switch (type)
{
case Types.ImageType:
//
break;
case Types.DataType:
//
break;
}
}
여기서 CreateType은 문자열 또는 유형으로 호출 할 수 있습니다. 그러나 단점은 모든 문자열이 자동으로 유효한 enum이라는 것입니다 . 이것은 수정할 수 있지만 일종의 init 함수가 필요합니다 ... 또는 명시 적으로 내부 캐스트로 만들 수 있습니까?
int 값이 (아마도 비교 속도) 당신에게 중요한 지금, 만약 당신이 할 수 야쿱 Šturc 환상적인 대답에서 몇 가지 아이디어를 사용하고 무언가 A가 할 비트 미친, 이것은 나의 자상입니다 :
public sealed class Types
{
private static readonly Dictionary<string, Types> strInstance = new Dictionary<string, Types>();
private static readonly Dictionary<int, Types> intInstance = new Dictionary<int, Types>();
private readonly String name;
private static int layerTypeCount = 0;
private int value;
private Types(String name)
{
this.name = name;
value = layerTypeCount++;
strInstance[name] = this;
intInstance[value] = this;
}
public override String ToString()
{
return name;
}
public static implicit operator Types(int val)
{
Types result;
if (intInstance.TryGetValue(val, out result))
return result;
else
throw new InvalidCastException();
}
public static implicit operator Types(string str)
{
Types result;
if (strInstance.TryGetValue(str, out result))
{
return result;
}
else
{
result = new Types(str);
return result;
}
}
public static implicit operator string(Types str)
{
return str.ToString();
}
public static bool operator ==(Types a, Types b)
{
return a.value == b.value;
}
public static bool operator !=(Types a, Types b)
{
return a.value != b.value;
}
#region enum
public const string DataType = "Data";
public const string ImageType = "Image";
#endregion
}
하지만 물론 "Types bob = 4;" 당신이 먼저 초기화하지 않았다면 의미가 없을 것입니다.
그러나 이론적으로 TypeA == TypeB는 더 빠를 것입니다 ...
내가 올바르게 이해하고 있다면 .ToString ()을 사용하여 값에서 열거 형 이름을 검색 할 수 있습니다 (이미 Enum으로 캐스팅되었다고 가정). naked int (데이터베이스 또는 다른 것에서 말한 것)가 있다면 먼저 열거 형으로 캐스팅 할 수 있습니다. 아래 두 방법 모두 열거 형 이름을 얻습니다.
AuthenticationMethod myCurrentSetting = AuthenticationMethod.FORMS;
Console.WriteLine(myCurrentSetting); // Prints: FORMS
string name = Enum.GetNames(typeof(AuthenticationMethod))[(int)myCurrentSetting-1];
Console.WriteLine(name); // Prints: FORMS
두 번째 기술은 int를 사용하고 인덱스가 1 기반 (0 기반 아님)이라고 가정합니다. GetNames 함수도 비교하면 상당히 무겁습니다. 호출 될 때마다 전체 배열을 생성합니다. 첫 번째 기술에서 볼 수 있듯이 .ToString ()은 실제로 암시 적으로 호출됩니다. 이 두 가지 모두 이미 답변에 언급되어 있지만 차이점을 명확히하려고 노력하고 있습니다.
이전 게시물이지만 ...
이에 대한 답은 실제로 매우 간단 할 수 있습니다. 사용 Enum.ToString () 함수를
이 함수에는 6 개의 오버로드가 있습니다. Enum.Tostring ( "F") 또는 Enum.ToString ()을 사용하여 문자열 값을 반환 할 수 있습니다. 다른 것에 신경을 쓸 필요가 없습니다. 다음은 작동하는 데모입니다.
이 솔루션은 모든 컴파일러에서 작동하지 않을 수 있지만 ( 이 데모는 예상대로 작동하지 않음 ) 적어도 최신 컴파일러에서는 작동합니다.
MSDN 기반 : http://msdn.microsoft.com/en-us/library/cc138362.aspx
foreach (string str in Enum.GetNames(typeof(enumHeaderField)))
{
Debug.WriteLine(str);
}
str은 필드의 이름입니다.
글쎄, 위의 모든 것을 읽은 후에 나는 사람들이 열거자를 문자열로 변환하는 문제를 너무 복잡하게 느꼈습니다. 열거 필드에 속성을 갖는 아이디어가 마음에 들었지만 속성은 주로 메타 데이터에 사용되지만 귀하의 경우 필요한 것은 일종의 현지화라고 생각합니다.
public enum Color
{ Red = 1, Green = 2, Blue = 3}
public static EnumUtils
{
public static string GetEnumResourceString(object enumValue)
{
Type enumType = enumValue.GetType();
string value = Enum.GetName(enumValue.GetType(), enumValue);
string resourceKey = String.Format("{0}_{1}", enumType.Name, value);
string result = Resources.Enums.ResourceManager.GetString(resourceKey);
if (string.IsNullOrEmpty(result))
{
result = String.Format("{0}", value);
}
return result;
}
}
이제 위의 메서드를 호출하려고하면 이렇게 호출 할 수 있습니다.
public void Foo()
{
var col = Color.Red;
Console.WriteLine (EnumUtils.GetEnumResourceString (col));
}
모든 열거 자 값과 해당 문자열을 포함하는 리소스 파일을 생성하기 만하면됩니다.
자원 이름 자원 값 Color_Red 내 문자열 색상 빨간색 Color_Blue Blueeey Color_Green 헐크 색상
실제로 매우 좋은 점은 응용 프로그램을 현지화해야하는 경우 매우 유용하다는 것입니다. 새 언어로 다른 리소스 파일을 만들기 만하면되기 때문입니다! 그리고 Voe-la!
이런 상황에 처했을 때 아래의 해결책을 제안합니다.
그리고 소비 클래스로서 당신은
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyApp.Dictionaries
{
class Greek
{
public static readonly string Alpha = "Alpha";
public static readonly string Beta = "Beta";
public static readonly string Gamma = "Gamma";
public static readonly string Delta = "Delta";
private static readonly BiDictionary<int, string> Dictionary = new BiDictionary<int, string>();
static Greek() {
Dictionary.Add(1, Alpha);
Dictionary.Add(2, Beta);
Dictionary.Add(3, Gamma);
Dictionary.Add(4, Delta);
}
public static string getById(int id){
return Dictionary.GetByFirst(id);
}
public static int getByValue(string value)
{
return Dictionary.GetBySecond(value);
}
}
}
그리고 양방향 사전 사용이 기준 ( https://stackoverflow.com/a/255638/986160 ) 키가 사전에 하나의 값과 연관되고 유사 할 것이라고 가정하면 ( https://stackoverflow.com/a / 255630 / 986160 )하지만 좀 더 우아합니다. 이 사전은 또한 열거 가능하며 정수에서 문자열로 앞뒤로 이동할 수 있습니다. 또한이 클래스를 제외하고 코드베이스에 문자열이 없어도됩니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace MyApp.Dictionaries
{
class BiDictionary<TFirst, TSecond> : IEnumerable
{
IDictionary<TFirst, TSecond> firstToSecond = new Dictionary<TFirst, TSecond>();
IDictionary<TSecond, TFirst> secondToFirst = new Dictionary<TSecond, TFirst>();
public void Add(TFirst first, TSecond second)
{
firstToSecond.Add(first, second);
secondToFirst.Add(second, first);
}
public TSecond this[TFirst first]
{
get { return GetByFirst(first); }
}
public TFirst this[TSecond second]
{
get { return GetBySecond(second); }
}
public TSecond GetByFirst(TFirst first)
{
return firstToSecond[first];
}
public TFirst GetBySecond(TSecond second)
{
return secondToFirst[second];
}
public IEnumerator GetEnumerator()
{
return GetFirstEnumerator();
}
public IEnumerator GetFirstEnumerator()
{
return firstToSecond.GetEnumerator();
}
public IEnumerator GetSecondEnumerator()
{
return secondToFirst.GetEnumerator();
}
}
}
더 큰 문자열 열거 세트의 경우 나열된 예제가 귀찮을 수 있습니다. 상태 코드 목록이나 다른 문자열 기반 열거 형 목록을 원하는 경우 속성 시스템은 사용하기가 성 가시고 자체 인스턴스가있는 정적 클래스는 구성하기가 귀찮습니다. 내 자신의 솔루션을 위해 T4 템플릿을 사용하여 문자열 지원 열거 형을 더 쉽게 만들 수 있습니다. 결과는 HttpMethod 클래스가 작동하는 방식과 유사합니다.
다음과 같이 사용할 수 있습니다.
string statusCode = ResponseStatusCode.SUCCESS; // Automatically converts to string when needed
ResponseStatusCode codeByValueOf = ResponseStatusCode.ValueOf(statusCode); // Returns null if not found
// Implements TypeConverter so you can use it with string conversion methods.
var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(ResponseStatusCode));
ResponseStatusCode code = (ResponseStatusCode) converter.ConvertFromInvariantString(statusCode);
// You can get a full list of the values
bool canIterateOverValues = ResponseStatusCode.Values.Any();
// Comparisons are by value of the "Name" property. Not by memory pointer location.
bool implementsByValueEqualsEqualsOperator = "SUCCESS" == ResponseStatusCode.SUCCESS;
Enum.tt 파일로 시작합니다.
<#@ include file="StringEnum.ttinclude" #>
<#+
public static class Configuration
{
public static readonly string Namespace = "YourName.Space";
public static readonly string EnumName = "ResponseStatusCode";
public static readonly bool IncludeComments = true;
public static readonly object Nodes = new
{
SUCCESS = "The response was successful.",
NON_SUCCESS = "The request was not successful.",
RESOURCE_IS_DISCONTINUED = "The resource requested has been discontinued and can no longer be accessed."
};
}
#>
그런 다음 StringEnum.ttinclude 파일에 추가합니다.
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#@ CleanupBehavior processor="T4VSHost" CleanupAfterProcessingtemplate="true" #>
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
namespace <#= Configuration.Namespace #>
{
/// <summary>
/// TypeConverter implementations allow you to use features like string.ToNullable(T).
/// </summary>
public class <#= Configuration.EnumName #>TypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var casted = value as string;
if (casted != null)
{
var result = <#= Configuration.EnumName #>.ValueOf(casted);
if (result != null)
{
return result;
}
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
var casted = value as <#= Configuration.EnumName #>;
if (casted != null && destinationType == typeof(string))
{
return casted.ToString();
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
[TypeConverter(typeof(<#= Configuration.EnumName #>TypeConverter))]
public class <#= Configuration.EnumName #> : IEquatable<<#= Configuration.EnumName #>>
{
//---------------------------------------------------------------------------------------------------
// V A L U E S _ L I S T
//---------------------------------------------------------------------------------------------------
<# Write(Helpers.PrintEnumProperties(Configuration.Nodes)); #>
private static List<<#= Configuration.EnumName #>> _list { get; set; } = null;
public static List<<#= Configuration.EnumName #>> ToList()
{
if (_list == null)
{
_list = typeof(<#= Configuration.EnumName #>).GetFields().Where(x => x.IsStatic && x.IsPublic && x.FieldType == typeof(<#= Configuration.EnumName #>))
.Select(x => x.GetValue(null)).OfType<<#= Configuration.EnumName #>>().ToList();
}
return _list;
}
public static List<<#= Configuration.EnumName #>> Values()
{
return ToList();
}
/// <summary>
/// Returns the enum value based on the matching Name of the enum. Case-insensitive search.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static <#= Configuration.EnumName #> ValueOf(string key)
{
return ToList().FirstOrDefault(x => string.Compare(x.Name, key, true) == 0);
}
//---------------------------------------------------------------------------------------------------
// I N S T A N C E _ D E F I N I T I O N
//---------------------------------------------------------------------------------------------------
public string Name { get; private set; }
public string Description { get; private set; }
public override string ToString() { return this.Name; }
/// <summary>
/// Implcitly converts to string.
/// </summary>
/// <param name="d"></param>
public static implicit operator string(<#= Configuration.EnumName #> d)
{
return d.ToString();
}
/// <summary>
/// Compares based on the == method. Handles nulls gracefully.
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static bool operator !=(<#= Configuration.EnumName #> a, <#= Configuration.EnumName #> b)
{
return !(a == b);
}
/// <summary>
/// Compares based on the .Equals method. Handles nulls gracefully.
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static bool operator ==(<#= Configuration.EnumName #> a, <#= Configuration.EnumName #> b)
{
return a?.ToString() == b?.ToString();
}
/// <summary>
/// Compares based on the .ToString() method
/// </summary>
/// <param name="o"></param>
/// <returns></returns>
public override bool Equals(object o)
{
return this.ToString() == o?.ToString();
}
/// <summary>
/// Compares based on the .ToString() method
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
public bool Equals(<#= Configuration.EnumName #> other)
{
return this.ToString() == other?.ToString();
}
/// <summary>
/// Compares based on the .Name property
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return this.Name.GetHashCode();
}
}
}
<#+
public static class Helpers
{
public static string PrintEnumProperties(object nodes)
{
string o = "";
Type nodesTp = Configuration.Nodes.GetType();
PropertyInfo[] props = nodesTp.GetProperties().OrderBy(p => p.Name).ToArray();
for(int i = 0; i < props.Length; i++)
{
var prop = props[i];
if (Configuration.IncludeComments)
{
o += "\r\n\r\n";
o += "\r\n ///<summary>";
o += "\r\n /// "+Helpers.PrintPropertyValue(prop, Configuration.Nodes);
o += "\r\n ///</summary>";
}
o += "\r\n public static readonly "+Configuration.EnumName+" "+prop.Name+ " = new "+Configuration.EnumName+"(){ Name = \""+prop.Name+"\", Description = "+Helpers.PrintPropertyValue(prop, Configuration.Nodes)+ "};";
}
o += "\r\n\r\n";
return o;
}
private static Dictionary<string, string> GetValuesMap()
{
Type nodesTp = Configuration.Nodes.GetType();
PropertyInfo[] props= nodesTp.GetProperties();
var dic = new Dictionary<string,string>();
for(int i = 0; i < props.Length; i++)
{
var prop = nodesTp.GetProperties()[i];
dic[prop.Name] = prop.GetValue(Configuration.Nodes).ToString();
}
return dic;
}
public static string PrintMasterValuesMap(object nodes)
{
Type nodesTp = Configuration.Nodes.GetType();
PropertyInfo[] props= nodesTp.GetProperties();
string o = " private static readonly Dictionary<string, string> ValuesMap = new Dictionary<string, string>()\r\n {";
for(int i = 0; i < props.Length; i++)
{
var prop = nodesTp.GetProperties()[i];
o += "\r\n { \""+prop.Name+"\", "+(Helpers.PrintPropertyValue(prop,Configuration.Nodes)+" },");
}
o += ("\r\n };\r\n");
return o;
}
public static string PrintPropertyValue(PropertyInfo prop, object objInstance)
{
switch(prop.PropertyType.ToString()){
case "System.Double":
return prop.GetValue(objInstance).ToString()+"D";
case "System.Float":
return prop.GetValue(objInstance).ToString()+"F";
case "System.Decimal":
return prop.GetValue(objInstance).ToString()+"M";
case "System.Long":
return prop.GetValue(objInstance).ToString()+"L";
case "System.Boolean":
case "System.Int16":
case "System.Int32":
return prop.GetValue(objInstance).ToString().ToLowerInvariant();
case "System.String":
return "\""+prop.GetValue(objInstance)+"\"";
}
return prop.GetValue(objInstance).ToString();
}
public static string _ (int numSpaces)
{
string o = "";
for(int i = 0; i < numSpaces; i++){
o += " ";
}
return o;
}
}
#>
마지막으로 Enum.tt 파일을 다시 컴파일하면 다음과 같은 출력이 표시됩니다.
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Linq;
using System.Collections.Generic;
namespace YourName.Space
{
public class ResponseStatusCode
{
//---------------------------------------------------------------------------------------------------
// V A L U E S _ L I S T
//---------------------------------------------------------------------------------------------------
///<summary>
/// "The response was successful."
///</summary>
public static readonly ResponseStatusCode SUCCESS = new ResponseStatusCode(){ Name = "SUCCESS", Description = "The response was successful."};
///<summary>
/// "The request was not successful."
///</summary>
public static readonly ResponseStatusCode NON_SUCCESS = new ResponseStatusCode(){ Name = "NON_SUCCESS", Description = "The request was not successful."};
///<summary>
/// "The resource requested has been discontinued and can no longer be accessed."
///</summary>
public static readonly ResponseStatusCode RESOURCE_IS_DISCONTINUED = new ResponseStatusCode(){ Name = "RESOURCE_IS_DISCONTINUED", Description = "The resource requested has been discontinued and can no longer be accessed."};
private static List<ResponseStatusCode> _list { get; set; } = null;
public static List<ResponseStatusCode> ToList()
{
if (_list == null)
{
_list = typeof(ResponseStatusCode).GetFields().Where(x => x.IsStatic && x.IsPublic && x.FieldType == typeof(ResponseStatusCode))
.Select(x => x.GetValue(null)).OfType<ResponseStatusCode>().ToList();
}
return _list;
}
public static List<ResponseStatusCode> Values()
{
return ToList();
}
/// <summary>
/// Returns the enum value based on the matching Name of the enum. Case-insensitive search.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static ResponseStatusCode ValueOf(string key)
{
return ToList().FirstOrDefault(x => string.Compare(x.Name, key, true) == 0);
}
//---------------------------------------------------------------------------------------------------
// I N S T A N C E _ D E F I N I T I O N
//---------------------------------------------------------------------------------------------------
public string Name { get; set; }
public string Description { get; set; }
public override string ToString() { return this.Name; }
/// <summary>
/// Implcitly converts to string.
/// </summary>
/// <param name="d"></param>
public static implicit operator string(ResponseStatusCode d)
{
return d.ToString();
}
/// <summary>
/// Compares based on the == method. Handles nulls gracefully.
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static bool operator !=(ResponseStatusCode a, ResponseStatusCode b)
{
return !(a == b);
}
/// <summary>
/// Compares based on the .Equals method. Handles nulls gracefully.
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static bool operator ==(ResponseStatusCode a, ResponseStatusCode b)
{
return a?.ToString() == b?.ToString();
}
/// <summary>
/// Compares based on the .ToString() method
/// </summary>
/// <param name="o"></param>
/// <returns></returns>
public override bool Equals(object o)
{
return this.ToString() == o?.ToString();
}
/// <summary>
/// Compares based on the .Name property
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return this.Name.GetHashCode();
}
}
}
Enum.GetName(typeof(MyEnum), (int)MyEnum.FORMS)
Enum.GetName(typeof(MyEnum), (int)MyEnum.WINDOWSAUTHENTICATION)
Enum.GetName(typeof(MyEnum), (int)MyEnum.SINGLESIGNON)
출력은 다음과 같습니다.
"양식"
"WINDOWSAUTHENTICATION"
"싱글 사인"
참고 URL : https://stackoverflow.com/questions/424366/string-representation-of-an-enum
'developer tip' 카테고리의 다른 글
Vim 레지스터는 어떻게 사용합니까? (0) | 2020.09.28 |
---|---|
jQuery를 사용하여 :: before 및 :: after와 같은 CSS 의사 요소 선택 및 조작 (0) | 2020.09.28 |
경쟁 조건이란 무엇입니까? (0) | 2020.09.28 |
반복하는 동안 목록에서 항목을 제거하는 방법은 무엇입니까? (0) | 2020.09.28 |
node.js에서 HTTP POST 요청은 어떻게 이루어 집니까? (0) | 2020.09.28 |