your programing

문자열 값으로 열거 형을 정의하는 방법은 무엇입니까?

lovepro 2020. 10. 8. 08:28
반응형

문자열 값으로 열거 형을 정의하는 방법은 무엇입니까?


EnumCSV 또는 유사한 파일에 사용되는 유효한 공통 구분 기호 를 정의 하고 추가 하려고 합니다. 그런 다음 ComboBoxEnum 정의에서 추가하거나 제거 할 때마다 콤보 상자에서 아무것도 변경할 필요가 없도록 데이터 소스로 바인딩 할 것입니다.

문제는 다음과 같이 문자열 표현으로 열거 형을 정의하는 방법입니다.

public enum SeparatorChars{Comma = ",", Tab = "\t", Space = " "}


당신은 할 수 없습니다-열거 형 값은 정수 값이어야합니다. 속성을 사용하여 문자열 값을 각 열거 형 값과 연결하거나이 경우 모든 구분 기호가 단일 문자 인 경우 char값을 사용할 수 있습니다 .

enum Separator
{
    Comma = ',',
    Tab = '\t',
    Space = ' '
}

(편집 : 명확히하기 위해 char열거 형의 기본 유형을 만들 수 는 없지만 char상수를 사용 하여 각 열거 형 값에 해당하는 정수 값을 할당 할 수 있습니다 . 위 열거 형의 기본 유형은입니다 int.)

그런 다음 필요한 경우 확장 방법 :

public string ToSeparatorString(this Separator separator)
{
    // TODO: validation
    return ((char) separator).ToString();
}

내가 아는 한 enum에 문자열 값을 할당 할 수 없습니다. 당신이 할 수있는 일은 그 안에 문자열 상수가있는 클래스를 만드는 것입니다.

public static class SeparatorChars
{
    public static String Comma { get { return ",";} } 
    public static String Tab { get { return "\t,";} } 
    public static String Space { get { return " ";} } 
}

당신은 그것을 달성 할 수 있지만 약간의 작업이 필요합니다.

  1. enum에 대한 문자열 값을 포함 할 속성 클래스를 정의하십시오.
  2. 속성에서 값을 반환 할 확장 메서드를 정의합니다. 예 : GetStringValue (이 Enum 값)는 속성 값을 반환합니다.
  3. 그런 다음 다음과 같이 열거 형을 정의 할 수 있습니다 ..
공개 열거 형 테스트 : int {
    [StringValue ( "a")]
    Foo = 1,
    [문자열 값 ( "b")]
    무언가 = 2        
} 
  1. Attrinbute Test.Foo.GetStringValue ();에서 값을 반환하려면

참조 : C #에서 문자열 값이있는 열거 형


열거 형으로는 이것을 할 수 없지만 다음과 같이 할 수 있습니다.

public static class SeparatorChars
{
    public static string Comma = ",";

    public static string Tab = "\t";

    public static string Space = " ";
}

단순 열거 형 문자열 값 (또는 기타 유형)의 경우 :

public static class MyEnumClass
{
    public const string 
        MyValue1 = "My value 1",
        MyValue2 = "My value 2";
}

용법: string MyValue = MyEnumClass.MyValue1;


enum은 기본 숫자 유형에만 기반 할 수 있기 때문에 불가능합니다. Dictionary대신 a 사용해 볼 수 있습니다 .

Dictionary<String, char> separators = new Dictionary<string, char>
{
    {"Comma", ','}, 
    {"Tab",  '\t'}, 
    {"Space", ' '},
};

또는 a Dictionary<Separator, char>또는 Dictionary<Separator, string>where Separatoris a normal enum을 사용할 수 있습니다 .

enum Separator
{
    Comma,
    Tab,
    Space
}

문자열을 직접 처리하는 것보다 조금 더 즐겁습니다.


열거 형 동작을 에뮬레이트하지만 string대신 사용하는 클래스는 int다음과 같이 만들 수 있습니다.

public class GrainType
{
    private string _typeKeyWord;

    private GrainType(string typeKeyWord)
    {
        _typeKeyWord = typeKeyWord;
    }

    public override string ToString()
    {
        return _typeKeyWord;
    }

    public static GrainType Wheat = new GrainType("GT_WHEAT");
    public static GrainType Corn = new GrainType("GT_CORN");
    public static GrainType Rice = new GrainType("GT_RICE");
    public static GrainType Barley = new GrainType("GT_BARLEY");

}

용법...

GrainType myGrain = GrainType.Wheat;

PrintGrainKeyword(myGrain);

그때...

public void PrintGrainKeyword(GrainType grain) 
{
    Console.Writeline("My Grain code is " + grain.ToString());   // Displays "My Grain code is GT_WHEAT"
}

대답하기에는 다소 늦었지만 미래에 누군가에게 도움이 될 수도 있습니다. 이런 종류의 문제에 struct를 사용하는 것이 더 쉽다는 것을 알았습니다.

다음 샘플은 MS 코드에서 붙여 넣은 부분을 복사합니다.

namespace System.IdentityModel.Tokens.Jwt
{
    //
    // Summary:
    //     List of registered claims from different sources http://tools.ietf.org/html/rfc7519#section-4
    //     http://openid.net/specs/openid-connect-core-1_0.html#IDToken
    public struct JwtRegisteredClaimNames
    {
        //
        // Summary:
        //     http://tools.ietf.org/html/rfc7519#section-4
        public const string Actort = "actort";
        //
        // Summary:
        //     http://tools.ietf.org/html/rfc7519#section-4
        public const string Typ = "typ";
        //
        // Summary:
        //     http://tools.ietf.org/html/rfc7519#section-4
        public const string Sub = "sub";
        //
        // Summary:
        //     http://openid.net/specs/openid-connect-frontchannel-1_0.html#OPLogout
        public const string Sid = "sid";
        //
        // Summary:
        //     http://tools.ietf.org/html/rfc7519#section-4
        public const string Prn = "prn";
        //
        // Summary:
        //     http://tools.ietf.org/html/rfc7519#section-4
        public const string Nbf = "nbf";
        //
        // Summary:
        //     http://tools.ietf.org/html/rfc7519#section-4
        public const string Nonce = "nonce";
        //
        // Summary:
        //     http://tools.ietf.org/html/rfc7519#section-4
        public const string NameId = "nameid";

    }
}

좀 더 일반적인 질문에 대한 답을 찾고있는 사람들을 위해 코드가 .NET Framework처럼 보이게하려면 정적 클래스 개념을 확장 할 수 있습니다 enum.

다음 접근 방식은 enum names원하는 것을 완료하지 않았고 enum valuesstring표현이 될 때 작동 합니다 enam name. nameof()리팩토링을 더 간단하게 만드는 데 사용 합니다.

public static class Colours
{
    public static string Red => nameof(Red);
    public static string Green => nameof(Green);
    public static string Blue => nameof(Blue);
}

이렇게하면 문자열 값 (예 : 다음 의사 코드)이있는 열거 형의 의도를 얻을 수 있습니다.

public enum Colours
{
    "Red",
    "Green",
    "Blue"
}

먼저 문자가 아닌 문자열을 지정하려고합니다. ","대신 ','를 사용하십시오. 다음으로 열거 형 char은 유니 코드 값을 사용할 수 없는 정수 유형 만 취하지 만 그렇게하지 말라고 강력하게 조언합니다. 이러한 값이 다른 문화와 언어에서 동일하게 유지된다는 확신이 들면 const 문자열이있는 정적 클래스를 사용합니다.


a char또는 a string를 열거 형의 기반으로 사용하는 것은 실제로 불가능하지만 이것이 당신이 정말로 좋아하는 것이 아니라고 생각합니다.

당신이 언급했듯이 당신은 가능성의 열거 형을 갖고 콤보 상자 안에 이것의 문자열 표현을 보여주고 싶습니다. 사용자가 이러한 문자열 표현 중 하나를 선택하면 해당 열거 형을 가져 오려고합니다. 그리고 이것은 가능합니다 :

먼저 일부 문자열을 열거 형 값에 연결해야합니다. 이것은 여기 또는 여기에DescriptionAttribute 설명 된 것과 같은 것을 사용하여 수행 할 수 있습니다 .

이제 열거 형 값 및 해당 설명 목록을 만들어야합니다. 다음 방법을 사용하여 수행 할 수 있습니다.

/// <summary>
/// Creates an List with all keys and values of a given Enum class
/// </summary>
/// <typeparam name="T">Must be derived from class Enum!</typeparam>
/// <returns>A list of KeyValuePair&lt;Enum, string&gt; with all available
/// names and values of the given Enum.</returns>
public static IList<KeyValuePair<T, string>> ToList<T>() where T : struct
{
    var type = typeof(T);

    if (!type.IsEnum)
    {
        throw new ArgumentException("T must be an enum");
    }

    return (IList<KeyValuePair<T, string>>)
            Enum.GetValues(type)
                .OfType<T>()
                .Select(e =>
                {
                    var asEnum = (Enum)Convert.ChangeType(e, typeof(Enum));
                    return new KeyValuePair<T, string>(e, asEnum.Description());
                })
                .ToArray();
}

이제 모든 열거 형 및 설명의 키 값 쌍 목록이 있습니다. 따라서 이것을 콤보 상자의 데이터 소스로 지정해 보겠습니다.

var comboBox = new ComboBox();
comboBox.ValueMember = "Key"
comboBox.DisplayMember = "Value";
comboBox.DataSource = EnumUtilities.ToList<Separator>();

comboBox.SelectedIndexChanged += (sender, e) =>
{
    var selectedEnum = (Separator)comboBox.SelectedValue;
    MessageBox.Show(selectedEnum.ToString());
}

사용자는 열거 형의 모든 문자열 표현을 볼 수 있으며 코드 내에서 원하는 열거 형 값을 얻을 수 있습니다.


여기에 몇 가지 답변을 바탕으로 열거 형의 동작을 모방하지만 string기본 유형으로 사용 하는 재사용 가능한 기본 클래스를 구현했습니다 . 다음을 포함한 다양한 작업을 지원합니다.

  1. 가능한 값 목록 얻기
  2. 문자열로 변환
  3. 다른 경우와 비교를 통해 .Equals, ==그리고!=
  4. JSON.NET JsonConverter를 사용하여 JSON으로 /에서 변환

이것은 전체적으로 기본 클래스입니다.

public abstract class StringEnumBase<T> : IEquatable<T>
    where T : StringEnumBase<T>
{
    public string Value { get; }

    protected StringEnumBase(string value) => this.Value = value;

    public override string ToString() => this.Value;

    public static List<T> AsList()
    {
        return typeof(T)
            .GetProperties(BindingFlags.Public | BindingFlags.Static)
            .Where(p => p.PropertyType == typeof(T))
            .Select(p => (T)p.GetValue(null))
            .ToList();
    }

    public static T Parse(string value)
    {
        List<T> all = AsList();

        if (!all.Any(a => a.Value == value))
            throw new InvalidOperationException($"\"{value}\" is not a valid value for the type {typeof(T).Name}");

        return all.Single(a => a.Value == value);
    }

    public bool Equals(T other)
    {
        if (other == null) return false;
        return this.Value == other?.Value;
    }

    public override bool Equals(object obj)
    {
        if (obj == null) return false;
        if (obj is T other) return this.Equals(other);
        return false;
    }

    public override int GetHashCode() => this.Value.GetHashCode();

    public static bool operator ==(StringEnumBase<T> a, StringEnumBase<T> b) => a?.Equals(b) ?? false;

    public static bool operator !=(StringEnumBase<T> a, StringEnumBase<T> b) => !(a?.Equals(b) ?? false);

    public class JsonConverter<T> : Newtonsoft.Json.JsonConverter
        where T : StringEnumBase<T>
    {
        public override bool CanRead => true;

        public override bool CanWrite => true;

        public override bool CanConvert(Type objectType) => ImplementsGeneric(objectType, typeof(StringEnumBase<>));

        private static bool ImplementsGeneric(Type type, Type generic)
        {
            while (type != null)
            {
                if (type.IsGenericType && type.GetGenericTypeDefinition() == generic)
                    return true;

                type = type.BaseType;
            }

            return false;
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            JToken item = JToken.Load(reader);
            string value = item.Value<string>();
            return StringEnumBase<T>.Parse(value);
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (value is StringEnumBase<T> v)
                JToken.FromObject(v.Value).WriteTo(writer);
        }
    }
}

그리고 이것은 "문자열 열거"를 구현하는 방법입니다.

[JsonConverter(typeof(JsonConverter<Colour>))]
public class Colour : StringEnumBase<Colour>
{
    private Colour(string value) : base(value) { }

    public static Colour Red => new Colour("red");
    public static Colour Green => new Colour("green");
    public static Colour Blue => new Colour("blue");
}

다음과 같이 사용할 수 있습니다.

public class Foo
{
    public Colour colour { get; }

    public Foo(Colour colour) => this.colour = colour;

    public bool Bar()
    {
        if (this.colour == Colour.Red || this.colour == Colour.Blue)
            return true;
        else
            return false;
    }
}

누군가 이것이 유용하다고 생각하기를 바랍니다!


열거 형을 문자열 유형으로 정의 할 수 없습니다. 열거 형에 대해 승인 된 유형은 byte, sbyte, short, ushort, int, uint, long 또는 ulong입니다.

열거에 대한 자세한 내용이 필요하면 아래 링크를 따르십시오. 해당 링크는 열거를 이해하는 데 도움이됩니다. 열거

안녕하세요.


저 한테는 효과가 있습니다 ..

   public class ShapeTypes
    {
        private ShapeTypes() { }
        public static string OVAL
        {
            get
            {
                return "ov";
            }
            private set { }
        }

        public static string SQUARE
        {
            get
            {
                return "sq";
            }
            private set { }
        }

        public static string RECTANGLE
        {
            get
            {
                return "rec";
            }
            private set { }
        }
    }

Enumaration 클래스

 public sealed class GenericDateTimeFormatType
    {

        public static readonly GenericDateTimeFormatType Format1 = new GenericDateTimeFormatType("dd-MM-YYYY");
        public static readonly GenericDateTimeFormatType Format2 = new GenericDateTimeFormatType("dd-MMM-YYYY");

        private GenericDateTimeFormatType(string Format)
        {
            _Value = Format;
        }

        public string _Value { get; private set; }
    }

에 누마 레이션 소비

public static void Main()
{
       Country A = new Country();

       A.DefaultDateFormat = GenericDateTimeFormatType.Format1;

      Console.ReadLine();
}

참고 URL : https://stackoverflow.com/questions/8588384/how-to-define-an-enum-with-string-value

반응형