Як отримати значення переліку за допомогою рядка або int


108

Як я можу отримати значення переліку, якщо я маю значення перерахування чи перерахування int значення. наприклад: Якщо у мене є перелік наступним чином:

public enum TestEnum
{
    Value1 = 1,
    Value2 = 2,
    Value3 = 3
}

і в деякій рядковій змінній я маю значення "value1" наступним чином:

string str = "Value1" 

або в якійсь змінній int я маю значення 2, як

int a = 2;

як я можу отримати екземпляр enum? Я хочу загальний метод, де я можу надати перелік та мій вхідний рядок або значення int, щоб отримати екземпляр переліку.


можливий дублікат значення Get enum int за допомогою рядка

Відповіді:


211

Ні, ви не хочете загального методу. Це набагато простіше:

MyEnum myEnum = (MyEnum)myInt;

MyEnum myEnum = (MyEnum)Enum.Parse(typeof(MyEnum), myString);

Думаю, це також буде швидше.


Це насправді правильний спосіб зробити це. Не існує загального способу синтаксичного аналізу типів з тієї самої причини, чому немає інтерфейсу IParsable.
Йоганнес

1
@Johannes Що ви маєте на увазі під цим? Існує загальний спосіб, зверніться до моєї відповіді та інших.
Шрірам Сактивель

1
@SriramSakthivel Проблема, яку описує OP, вирішена, як це показав KendallFrey. Загальний синтаксичний аналіз неможливо зробити - див. Тут: informit.com/blogs/blog.aspx?uk=Why-no-IParseable-interface . Будь-яке інше рішення не має переваг порівняно з "бортовим" рішенням C #. Максимум, що ви можете мати, - це ICanSetFromString <T>, де ви створюєте та ініціалізуєте об’єкт за замовчуванням (T), а на наступному кроці передаєте репрезентативний рядок. Це близько до відповіді, яку дав ОП, але це безглуздо, оскільки зазвичай це питання дизайну, і більший момент у проектуванні системи був пропущений.
Йоганнес

Ця відповідь працювала дуже добре, особливо з численними прикладами використання int та string. Дякую.
Термато

1
Я думаю, це працює зараз, це трохи лаконічніше: Enum.Parse <MyEnum> (myString);
Філ Б

32

Існує безліч способів зробити це, але якщо ви хочете простий приклад, це стане в нагоді. Його просто потрібно посилити необхідним захисним кодуванням, щоб перевірити безпеку типу та недійсний синтаксичний аналіз тощо.

    /// <summary>
    /// Extension method to return an enum value of type T for the given string.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <returns></returns>
    public static T ToEnum<T>(this string value)
    {
        return (T) Enum.Parse(typeof(T), value, true);
    }

    /// <summary>
    /// Extension method to return an enum value of type T for the given int.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <returns></returns>
    public static T ToEnum<T>(this int value)
    {
        var name = Enum.GetName(typeof(T), value);
        return name.ToEnum<T>();
    }

17

Може бути набагато простіше, якщо ви використовуєте TryParseабо Parseі ToObjectметоди.

public static class EnumHelper
{
    public static  T GetEnumValue<T>(string str) where T : struct, IConvertible
    {
        Type enumType = typeof(T);
        if (!enumType.IsEnum)
        {
            throw new Exception("T must be an Enumeration type.");
        }
        T val;
        return Enum.TryParse<T>(str, true, out val) ? val : default(T);
    }

    public static T GetEnumValue<T>(int intValue) where T : struct, IConvertible
    {
        Type enumType = typeof(T);
        if (!enumType.IsEnum)
        {
            throw new Exception("T must be an Enumeration type.");
        }

        return (T)Enum.ToObject(enumType, intValue);
    }
}

Як зазначав @chrfin в коментарях, ви можете зробити його методом розширення дуже легко, просто додавши thisперед типом параметра, який може бути зручним.


2
Тепер також додайте thisдо параметра параметр і зробіть EnumHelperстатичним, і ви також можете використовувати їх як розширення (див. Мою відповідь, але у вас є кращий / повний код для решти) ...
Крістоф Фінк

@chrfin Хороша ідея, але я не віддаю перевагу їй, оскільки вона буде з’являтися в intellisense там, де це не потрібно, коли у нас є простори імен. Напевно це буде дратувати.
Шрірам Сактивель

1
@chrfin Дякую за коментар, доданий як примітка до моєї відповіді.
Шрірам Сактивель

5

Нижче наведено метод у C # для отримання значення переліку за допомогою рядка

///
/// Method to get enumeration value from string value.
///
///
///

public T GetEnumValue<T>(string str) where T : struct, IConvertible
{
    if (!typeof(T).IsEnum)
    {
        throw new Exception("T must be an Enumeration type.");
    }
    T val = ((T[])Enum.GetValues(typeof(T)))[0];
    if (!string.IsNullOrEmpty(str))
    {
        foreach (T enumValue in (T[])Enum.GetValues(typeof(T)))
        {
            if (enumValue.ToString().ToUpper().Equals(str.ToUpper()))
            {
                val = enumValue;
                break;
            }
        }
    }

    return val;
}

Нижче наведено метод у C # для отримання значення перерахування за допомогою int.

///
/// Method to get enumeration value from int value.
///
///
///

public T GetEnumValue<T>(int intValue) where T : struct, IConvertible
{
    if (!typeof(T).IsEnum)
    {
        throw new Exception("T must be an Enumeration type.");
    }
    T val = ((T[])Enum.GetValues(typeof(T)))[0];

    foreach (T enumValue in (T[])Enum.GetValues(typeof(T)))
    {
        if (Convert.ToInt32(enumValue).Equals(intValue))
        {
            val = enumValue;
            break;
        }             
    }
    return val;
}

Якщо я маю перелік наступним чином:

public enum TestEnum
{
    Value1 = 1,
    Value2 = 2,
    Value3 = 3
}

тоді я можу скористатися наведеними вище методами як

TestEnum reqValue = GetEnumValue<TestEnum>("Value1");  // Output: Value1
TestEnum reqValue2 = GetEnumValue<TestEnum>(2);        // OutPut: Value2

Сподіваюся, це допоможе.


4
Чи можете ви також надати посилання на те, де ви це взяли?
JonH

Для компіляції мені довелося змінити перший рядок на загальнодоступний T GetEnumValue <T> (int intValue), де T: struct, IConvertible Також остерігайтеся зайвого '}' наприкінці
Avi

3

Я думаю, ви забули загальне визначення типу:

public T GetEnumValue<T>(int intValue) where T : struct, IConvertible // <T> added

і ви можете покращити його, щоб він був найбільш зручним, наприклад, наприклад:

public static T ToEnum<T>(this string enumValue) : where T : struct, IConvertible
{
    return (T)Enum.Parse(typeof(T), enumValue);
}

тоді ви можете зробити:

TestEnum reqValue = "Value1".ToEnum<TestEnum>();

2

Спробуйте щось подібне

  public static TestEnum GetMyEnum(this string title)
        {    
            EnumBookType st;
            Enum.TryParse(title, out st);
            return st;          
         }

Так ти можеш зробити

TestEnum en = "Value1".GetMyEnum();

2

З бази даних SQL отримати перелічення, як:

SqlDataReader dr = selectCmd.ExecuteReader();
while (dr.Read()) {
   EnumType et = (EnumType)Enum.Parse(typeof(EnumType), dr.GetString(0));
   ....         
}

2

Просто спробуйте це

Це інший спосіб

public enum CaseOriginCode
{
    Web = 0,
    Email = 1,
    Telefoon = 2
}

public void setCaseOriginCode(string CaseOriginCode)
{
    int caseOriginCode = (int)(CaseOriginCode)Enum.Parse(typeof(CaseOriginCode), CaseOriginCode);
}

0

Ось приклад отримання рядка / значення

    public enum Suit
    {
        Spades = 0x10,
        Hearts = 0x11,
        Clubs = 0x12,
        Diamonds = 0x13
    }

    private void print_suit()
    {
        foreach (var _suit in Enum.GetValues(typeof(Suit)))
        {
            int suitValue = (byte)(Suit)Enum.Parse(typeof(Suit), _suit.ToString());
            MessageBox.Show(_suit.ToString() + " value is 0x" + suitValue.ToString("X2"));
        }
    }

    Result of Message Boxes
    Spade value is 0x10
    Hearts value is 0x11
    Clubs value is 0x12
    Diamonds value is 0x13

0

Для цього можна використати наступний метод:

public static Output GetEnumItem<Output, Input>(Input input)
    {
        //Output type checking...
        if (typeof(Output).BaseType != typeof(Enum))
            throw new Exception("Exception message...");

        //Input type checking: string type
        if (typeof(Input) == typeof(string))
            return (Output)Enum.Parse(typeof(Output), (dynamic)input);

        //Input type checking: Integer type
        if (typeof(Input) == typeof(Int16) ||
            typeof(Input) == typeof(Int32) ||
            typeof(Input) == typeof(Int64))

            return (Output)(dynamic)input;

        throw new Exception("Exception message...");
    }

Примітка: цей метод є лише зразком, і його можна вдосконалити.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.