Як подати int до перерахунку?


Відповіді:


3790

З рядка:

YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString);

// The foo.ToString().Contains(",") check is necessary for enumerations marked with an [Flags] attribute
if (!Enum.IsDefined(typeof(YourEnum), foo) && !foo.ToString().Contains(","))
{
    throw new InvalidOperationException($"{yourString} is not an underlying value of the YourEnum enumeration.")
}

З int:

YourEnum foo = (YourEnum)yourInt;

Оновлення:

З номера ви також можете

YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);

31
@FlySwat, що робити, якщо YourEnumце динамічно і стане відомо лише під час виконання, і що я хочу це перетворити Enum?
Шиммі Вайцхандлер

226
Майте на увазі, що Enum.Parse НЕ працюватиме, якщо ваш код затуманений. Під час запуску після обфускування рядок порівнюється з іменами перерахунків, і на даний момент назви переліків не є такими, якими ви б їх очікували. Ваш аналіз не зможе там, де їм це вдалося раніше.
jropella

158
ПОПЕРЕДЖЕННЯ Якщо ви використовуєте синтаксис "з рядка" вище і передаєте недійсний рядок, який є числом (наприклад, "2342342" - якщо припустити, що це не значення вашої перерахунку), це фактично дозволить це, не видаючи помилку! Ваш перелік матиме це значення (2342342), навіть якщо це не є правильним вибором у самій перерахунку.
JoeCool

132
Я думаю, що ця відповідь трохи датована зараз. Для рядка, ви дійсно повинні використовувати var result = Enum.TryParse(yourString, out yourEnum)сьогодні (і перевірити результат, щоб визначити, чи не вдалося перетворити).
Джастін Т Конрой

20
Можна також Enum.Parseбути нечутливими до регістру, додавши trueдо виклику значення параметра:YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString, true);
Erik Schierboom

900

Просто киньте його:

MyEnum e = (MyEnum)3;

Ви можете перевірити, чи знаходиться він у діапазоні, використовуючи Enum.IsDefined :

if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }

218
Остерігайтеся, що ви не можете використовувати Enum.IsDefined, якщо ви використовуєте атрибут Flags, а значення є комбінацією прапорів, наприклад: Keys.L | Keys.Control
dtroy

15
Щодо цього Enum.IsDefined, майте на увазі, що це може бути небезпечно: msdn.microsoft.com/en-us/library/ms229025(VS.90).aspx
adrian

3
Я віддаю перевагу цьому визначенню: "Повертає вказівку, чи існує константа із заданим значенням у вказаному перерахуванні" з MSDN
Pap

3
... Тому що ваше визначення може ввести в оману, тому що ви говорите: «... перевірити , якщо він знаходиться в межах ...» , який передбачає в діапазоні чисел , починаючи і закінчуючи межі ...
Пап

3
@ mac9416 Я намагався навести стислий приклад на gist.github.com/alowdon/f7354cda97bac70b44e1c04bc0991bcc - в основному, використовуючи IsDefinedдля перевірки вхідних значень, ви залишаєте себе вразливим до людей, додаючи нові значення перерахунків пізніше, які пройдуть IsDefinedперевірку (оскільки нові значення існує в новому коді), але це може не працювати з оригінальним кодом, який ви написали. Тому безпечніше чітко вказати значення перерахунків, з якими може працювати ваш код.
Адріан

238

Крім того, використовуйте метод розширення замість однолінійного:

public static T ToEnum<T>(this string enumString)
{
    return (T) Enum.Parse(typeof (T), enumString);
}

Використання:

Color colorEnum = "Red".ToEnum<Color>();

АБО

string color = "Red";
var colorEnum = color.ToEnum<Color>();

7
Для обробки вводу користувача, ймовірно, буде гарною ідеєю викликати перевантаження Enum.Parse, що дозволяє вказати, що порівняння НЕ має бути чутливим до регістру (тобто користувач, який вводить "червоний" (нижній регістр), призведе до краху вищевказаного коду без цієї зміни .)
BrainSlugs83

9
Зручно, але питання спеціально задається про вклад.
БЮР

2
це також працює, якщо рядок є цілим числом, наприклад, "2"
TruthOf42

2
Це викине виняток, якщо enumString є нульовим (мала подібну проблему вчора). Подумайте про використання TryParse замість Parse. TryParse також перевірить, чи T - це тип Enum
Джастін

Цей тип методу розширення System.Stringвиглядає як забруднення простору імен
пан Андерсон

160

Я думаю, щоб отримати повну відповідь, люди повинні знати, як енуми працюють у .NET.

Як працює матеріал

Перерахунок у .NET - це структура, яка відображає набір значень (полів) до базового типу (типовим є int). Однак ви можете фактично вибрати інтегральний тип, на який відображається ваш перелік:

public enum Foo : short

У цьому випадку перерахунок відображається на shortтип даних, а це означає, що він буде зберігатися в пам'яті як короткий і буде вести себе як короткий при передачі та використанні.

Якщо ви дивитесь на це з точки зору ІЛ, перерахунок (нормальний, внутрішній) виглядає так:

.class public auto ansi serializable sealed BarFlag extends System.Enum
{
    .custom instance void System.FlagsAttribute::.ctor()
    .custom instance void ComVisibleAttribute::.ctor(bool) = { bool(true) }

    .field public static literal valuetype BarFlag AllFlags = int32(0x3fff)
    .field public static literal valuetype BarFlag Foo1 = int32(1)
    .field public static literal valuetype BarFlag Foo2 = int32(0x2000)

    // and so on for all flags or enum values

    .field public specialname rtspecialname int32 value__
}

Тут слід звернути вашу увагу на те, що значення value__зберігається окремо від значень enum. У випадку перерахунку Fooвище тип value__int16. Це в основному означає, що ви можете зберігати все, що завгодно, в кількості, доки типи відповідають .

На цьому етапі я хотів би зазначити, що System.Enumце тип значення, який в основному означає, що BarFlagвін займе 4 байти в пам'яті і Fooзайме 2 - наприклад, розмір базового типу (це насправді складніше, ніж це, але гей ...).

Відповідь

Отже, якщо у вас є ціле число, яке ви хочете зіставити на enum, час виконання повинен виконати лише 2 речі: скопіювати 4 байти та назвати його чимось іншим (назва enum). Копіювання є неявним, оскільки дані зберігаються як тип значення - це в основному означає, що якщо ви використовуєте некерований код, ви можете просто обмінятись перерахуваннями і цілими числами без копіювання даних.

Щоб зробити це безпечним, я вважаю, що найкраща практика знати, що основні типи однакові або неявно конвертовані та забезпечити існування значень enum (вони не перевіряються за замовчуванням!).

Щоб побачити, як це працює, спробуйте наступний код:

public enum MyEnum : int
{
    Foo = 1,
    Bar = 2,
    Mek = 5
}

static void Main(string[] args)
{
    var e1 = (MyEnum)5;
    var e2 = (MyEnum)6;

    Console.WriteLine("{0} {1}", e1, e2);
    Console.ReadLine();
}

Зауважте, що кастинг e2також працює! З точки зору компілятора вище це має сенс: value__поле просто заповнюється або 5, або 6, і коли Console.WriteLineдзвінки ToString(), ім'я e1вирішується, а ім'я e2- ні.

Якщо це не те, що ви задумали, скористайтеся, Enum.IsDefined(typeof(MyEnum), 6)щоб перевірити, чи значення ви перекидаєте на певний перелік.

Також зауважте, що я чітко описую базовий тип перерахунку, хоча компілятор насправді перевіряє це. Я роблю це для того, щоб не стикатися з жодними сюрпризами. Щоб побачити ці сюрпризи в дії, ви можете скористатися наступним кодом (насправді я бачив, що це відбувається багато в коді бази даних):

public enum MyEnum : short
{
    Mek = 5
}

static void Main(string[] args)
{
    var e1 = (MyEnum)32769; // will not compile, out of bounds for a short

    object o = 5;
    var e2 = (MyEnum)o;     // will throw at runtime, because o is of type int

    Console.WriteLine("{0} {1}", e1, e2);
    Console.ReadLine();
}

7
Я усвідомлюю, що це стара публікація, але як ви здобуваєте цей рівень знань на c #? Це з читання через специфікацію C #?
Ролан

20
@Rolan Я іноді бажаю, щоб більше людей запитували це. :-) Чесно кажучи, я насправді не знаю; Я намагаюся зрозуміти, як все працює, і отримую інформацію, де я можу її отримати. Я читав стандарт C #, але також регулярно декомпілюю код з Reflector (я навіть дуже багато дивлюсь на код асемблера x86) і роблю безліч експериментів. Також знання про інші мови допомагає в цьому випадку; Я займаюся CS вже близько 30 років, і в якийсь момент певні речі стають «логічними» - f.ex. enum має інтегрувати типи, тому що в іншому випадку interop порушиться (інакше ваша продуктивність знизиться).
atlaste

9
Я вважаю, що головне для правильної інженерії програмного забезпечення - це знати, як працює робота. Для мене це означає, що якщо ви пишете фрагмент коду, ви знаєте, як він грубо перекладається на f.ex. операції процесора та витяг / запис пам'яті. Якщо ви запитаєте, як досягти цього рівня, я б запропонував створити малу кількість невеликих тестових випадків, зробивши їх більш жорсткими, коли ви йдете, намагайтеся передбачити результат кожного разу і перевіряйте їх після цього (включаючи декомпіляцію тощо). Вияснивши всі деталі та всі характеристики, ви можете перевірити, чи правильно ви це зрозуміли у (нудному) стандарті. Принаймні, це був би мій підхід.
атлас

1
Фантастична відповідь, дякую! У вашому останньому зразку коду він видає виняток під час виконання, оскільки o - об'єкт. Ви можете присвоїти змінну int до короткого, доки вона не потрапить у короткий діапазон.
gravidThoughts

@gravidThoughts Дякую Насправді це операція розпакування, тому вона не здійснюватиме неявних перетворень, як те, що ви описуєте. Кастинг іноді плутається в C #, якщо ви не знаєте подробиць ... Так чи інакше, тому що int! = short, Він буде кинутий (вимикання не працює). Якщо ви це зробите object o = (short)5;, це спрацює, бо тоді типи будуть відповідати. Мова не про асортимент, це справді про тип.
атлас


64

Я використовую цей фрагмент коду, щоб подати int моєму перерахунку:

if (typeof(YourEnum).IsEnumDefined(valueToCast)) return (YourEnum)valueToCast;
else { //handle it here, if its not defined }

Я вважаю це найкращим рішенням.


1
це добре. Я був здивований, що не є винятком, коли викидаєте недійсне значення до переліченого Int.
orion elenzil

Це насправді не так вже й відрізняється, ніж відповідь з найвищим рейтингом. У цій відповіді також обговорюється використання Enum.IsDefined після того, як ви передали рядок типу Enum. Тож навіть якщо струна була передана без помилок, Enum.IsDefined все одно її впіймає
Don Cheadle

53

Нижче представлений приємний клас корисності для Enums

public static class EnumHelper
{
    public static int[] ToIntArray<T>(T[] value)
    {
        int[] result = new int[value.Length];
        for (int i = 0; i < value.Length; i++)
            result[i] = Convert.ToInt32(value[i]);
        return result;
    }

    public static T[] FromIntArray<T>(int[] value) 
    {
        T[] result = new T[value.Length];
        for (int i = 0; i < value.Length; i++)
            result[i] = (T)Enum.ToObject(typeof(T),value[i]);
        return result;
    }


    internal static T Parse<T>(string value, T defaultValue)
    {
        if (Enum.IsDefined(typeof(T), value))
            return (T) Enum.Parse(typeof (T), value);

        int num;
        if(int.TryParse(value,out num))
        {
            if (Enum.IsDefined(typeof(T), num))
                return (T)Enum.ToObject(typeof(T), num);
        }

        return defaultValue;
    }
}

47

Для числових значень це безпечніше, оскільки він поверне об'єкт незалежно від того, що:

public static class EnumEx
{
    static public bool TryConvert<T>(int value, out T result)
    {
        result = default(T);
        bool success = Enum.IsDefined(typeof(T), value);
        if (success)
        {
            result = (T)Enum.ToObject(typeof(T), value);
        }
        return success;
    }
}

Не працює для перерахування прапорів
Seyed Morteza Mousavi


35

Якщо у вас є ціле число, яке виступає в якості бітової маски і могло представляти одне або більше значень у переліку [Флаги], ви можете використовувати цей код для розбору окремих значень прапора у списку:

for (var flagIterator = 0; flagIterator < 32; flagIterator++)
{
    // Determine the bit value (1,2,4,...,Int32.MinValue)
    int bitValue = 1 << flagIterator;

    // Check to see if the current flag exists in the bit mask
    if ((intValue & bitValue) != 0)
    {
        // If the current flag exists in the enumeration, then we can add that value to the list
        // if the enumeration has that flag defined
        if (Enum.IsDefined(typeof(MyEnum), bitValue))
            Console.WriteLine((MyEnum)bitValue);
    }
}

Зауважимо, що це передбачає, що базовим типом значення enumє підписане 32-бітове ціле число. Якби це був інший числовий тип, вам доведеться змінити твердо кодований 32, щоб відобразити біти цього типу (або програмно вивести його за допомогою Enum.GetUnderlyingType())


1
Невже ця петля ніколи не припиняється? flagIterator = 0x00000001, flagIterator = 0x00000002, flagIterator = 0x00000004, ..., flagIterator = 0x40000000, flagIterator = 0x80000000, flagIterator = 0x00000000. Іншими словами, значення завжди буде нижчим за 0x80000000, тому що воно переповнюється до нуля після випадку, коли біт D31 = 1. Тоді воно назавжди залишається 0, оскільки зміщення вліво значення 0 дає 0
Крістіан

Чудовий улов @christiangingras, дякую! Я змінив відповідь, щоб врахувати це, і він повинен враховувати, коли встановлено найвищий біт (тобто 0x80000000 / Int32.MinValue)
Evan M

27

Іноді у вас є об’єкт MyEnumтипу. Подібно до

var MyEnumType = typeof(MyEnumType);

Тоді:

Enum.ToObject(typeof(MyEnum), 3)

26

Це прапор переліку безпечних методів перерахування прапорів:

public static bool TryConvertToEnum<T>(this int instance, out T result)
  where T: Enum
{
  var enumType = typeof (T);
  var success = Enum.IsDefined(enumType, instance);
  if (success)
  {
    result = (T)Enum.ToObject(enumType, instance);
  }
  else
  {
    result = default(T);
  }
  return success;
}

3
Тепер це можна покращити за допомогою C # 7.3, обмежившись Enumзамість цього struct, тобто ми не повинні покладатися на перевірку часу виконання!
Скотт

20

введіть тут опис зображення

Для перетворення рядка в ENUM або int в ENUM константу нам потрібно використовувати функцію Enum.Parse. Ось відео https://www.youtube.com/watch?v=4nhx4VwdRDk на YouTube, яке фактично демонструє, є рядком і те саме стосується int.

Код йде так, як показано нижче, де "червоний" є рядком, а "MyColors" - кольором ENUM, який має кольорові константи.

MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");

20

Трохи відходячи від початкового запитання, але я знайшов відповідь на питання Stack Overflow Отримати значення int від enum корисно. Створіть статичний клас із public const intвластивостями, що дозволяє легко збирати купу пов’язаних intконстант, а потім не потрібно наводити їх під intчас їх використання.

public static class Question
{
    public static readonly int Role = 2;
    public static readonly int ProjectFunding = 3;
    public static readonly int TotalEmployee = 4;
    public static readonly int NumberOfServers = 5;
    public static readonly int TopBusinessConcern = 6;
}

Очевидно, частина функцій типу enum буде втрачена, але для зберігання купи констант ідентифікаторів бази даних це здається досить акуратним рішенням.


5
перерахунки витіснили використання таких цілих констант, оскільки вони забезпечують більшу безпеку типу
Пол Річардс,

1
Павло, це метод збирання спільно пов'язаних int-констант (наприклад, константи бази даних ID), щоб їх можна було використовувати безпосередньо, без того, щоб кидати їх до int кожного разу, коли вони використовуються. Їх тип є цілим числом, а не, наприклад, DatabaseIdsEnum.
Тед

1
Принаймні одна ситуація, яку я виявив, у якій безпеку типу перешкод можна ненавмисно обійти.
Тьєррі

Але перелічені люди також переконують, що цінність є унікальною, чогось цього підходу теж не вистачає
derHugo

15

Це аналізує цілі числа чи рядки до цільового перерахунку з частковим узгодженням у dot.NET 4.0, використовуючи дженерики, як у клас утиліти Тавані вище. Я використовую його для перетворення змінних командного рядка, які можуть бути неповними. Оскільки enum не може бути нульовим, вам слід логічно вказати значення за замовчуванням. Це можна назвати так:

var result = EnumParser<MyEnum>.Parse(valueToParse, MyEnum.FirstValue);

Ось код:

using System;

public class EnumParser<T> where T : struct
{
    public static T Parse(int toParse, T defaultVal)
    {
        return Parse(toParse + "", defaultVal);
    }
    public static T Parse(string toParse, T defaultVal) 
    {
        T enumVal = defaultVal;
        if (defaultVal is Enum && !String.IsNullOrEmpty(toParse))
        {
            int index;
            if (int.TryParse(toParse, out index))
            {
                Enum.TryParse(index + "", out enumVal);
            }
            else
            {
                if (!Enum.TryParse<T>(toParse + "", true, out enumVal))
                {
                    MatchPartialName(toParse, ref enumVal);
                }
            }
        }
        return enumVal;
    }

    public static void MatchPartialName(string toParse, ref T enumVal)
    {
        foreach (string member in enumVal.GetType().GetEnumNames())
        {
            if (member.ToLower().Contains(toParse.ToLower()))
            {
                if (Enum.TryParse<T>(member + "", out enumVal))
                {
                    break;
                }
            }
        }
    }
}

FYI: Питання стосувалося цілих чисел, про які ніхто не згадував також явно перетворить в Enum.TryParse ()


13

З рядка: (Enum.Parse застарів, використовуйте Enum.TryParse)

enum Importance
{}

Importance importance;

if (Enum.TryParse(value, out importance))
{
}

4
Питання спеціально задає цілі числа.
БЮР

4
Буде Ю, будь ласка, відредагуйте свою відповідь, щоб усі знали Enum.TryParse буде працювати над рядком значення або імені перерахунку (я не міг протистояти)
JeremyWeir

1
Джеремі, Вейр працював над цим (не встояв ні перед тим).
huysentruitw

11

Далі йде трохи кращий спосіб розширення

public static string ToEnumString<TEnum>(this int enumValue)
        {
            var enumString = enumValue.ToString();
            if (Enum.IsDefined(typeof(TEnum), enumValue))
            {
                enumString = ((TEnum) Enum.ToObject(typeof (TEnum), enumValue)).ToString();
            }
            return enumString;
        }

10

У моєму випадку мені потрібно було повернути перерахунок із служби WCF. Мені також потрібне було дружнє ім’я, а не лише enum.ToString ().

Ось мій клас WCF.

[DataContract]
public class EnumMember
{
    [DataMember]
    public string Description { get; set; }

    [DataMember]
    public int Value { get; set; }

    public static List<EnumMember> ConvertToList<T>()
    {
        Type type = typeof(T);

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

        var members = new List<EnumMember>();

        foreach (string item in System.Enum.GetNames(type))
        {
            var enumType = System.Enum.Parse(type, item);

            members.Add(
                new EnumMember() { Description = enumType.GetDescriptionValue(), Value = ((IConvertible)enumType).ToInt32(null) });
        }

        return members;
    }
}

Ось метод розширення, який отримує Опис від Enum.

    public static string GetDescriptionValue<T>(this T source)
    {
        FieldInfo fileInfo = source.GetType().GetField(source.ToString());
        DescriptionAttribute[] attributes = (DescriptionAttribute[])fileInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);            

        if (attributes != null && attributes.Length > 0)
        {
            return attributes[0].Description;
        }
        else
        {
            return source.ToString();
        }
    }

Впровадження:

return EnumMember.ConvertToList<YourType>();

9

Я більше не знаю, звідки я беру частину цього розширення enum, але це від stackoverflow. Мені шкода за це! Але я взяв цей і змінив його на перерахунки з Прапорами. Для переліків із прапорами я зробив це:

  public static class Enum<T> where T : struct
  {
     private static readonly IEnumerable<T> All = Enum.GetValues(typeof (T)).Cast<T>();
     private static readonly Dictionary<int, T> Values = All.ToDictionary(k => Convert.ToInt32(k));

     public static T? CastOrNull(int value)
     {
        T foundValue;
        if (Values.TryGetValue(value, out foundValue))
        {
           return foundValue;
        }

        // For enums with Flags-Attribut.
        try
        {
           bool isFlag = typeof(T).GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0;
           if (isFlag)
           {
              int existingIntValue = 0;

              foreach (T t in Enum.GetValues(typeof(T)))
              {
                 if ((value & Convert.ToInt32(t)) > 0)
                 {
                    existingIntValue |= Convert.ToInt32(t);
                 }
              }
              if (existingIntValue == 0)
              {
                 return null;
              }

              return (T)(Enum.Parse(typeof(T), existingIntValue.ToString(), true));
           }
        }
        catch (Exception)
        {
           return null;
        }
        return null;
     }
  }

Приклад:

[Flags]
public enum PetType
{
  None = 0, Dog = 1, Cat = 2, Fish = 4, Bird = 8, Reptile = 16, Other = 32
};

integer values 
1=Dog;
13= Dog | Fish | Bird;
96= Other;
128= Null;

9

Вам слід створити відповідні релакси типу, щоб бути більш надійними.

public static T ToEnum<T>(dynamic value)
{
    if (value == null)
    {
        // default value of an enum is the object that corresponds to
        // the default value of its underlying type
        // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/default-values-table
        value = Activator.CreateInstance(Enum.GetUnderlyingType(typeof(T)));
    }
    else if (value is string name)
    {
        return (T)Enum.Parse(typeof(T), name);
    }

    return (T)Enum.ToObject(typeof(T),
             Convert.ChangeType(value, Enum.GetUnderlyingType(typeof(T))));
}

Тестовий випадок

[Flags]
public enum A : uint
{
    None  = 0, 
    X     = 1 < 0,
    Y     = 1 < 1
}

static void Main(string[] args)
{
    var value = EnumHelper.ToEnum<A>(7m);
    var x = value.HasFlag(A.X); // true
    var y = value.HasFlag(A.Y); // true

    var value2 = EnumHelper.ToEnum<A>("X");

    var value3 = EnumHelper.ToEnum<A>(null);

    Console.ReadKey();
}

Це приємна відповідь. Прикро, що зараз так далеко внизу сторінки!
MikeBeaton

8

Різні способи подачі на та з нього Enum

enum orientation : byte
{
 north = 1,
 south = 2,
 east = 3,
 west = 4
}

class Program
{
  static void Main(string[] args)
  {
    orientation myDirection = orientation.north;
    Console.WriteLine(“myDirection = {0}”, myDirection); //output myDirection =north
    Console.WriteLine((byte)myDirection); //output 1

    string strDir = Convert.ToString(myDirection);
        Console.WriteLine(strDir); //output north

    string myString = north”; //to convert string to Enum
    myDirection = (orientation)Enum.Parse(typeof(orientation),myString);


 }
}

8

Це може допомогти вам перетворити будь-які вхідні дані в потрібні користувачеві enum . Припустимо, у вас є enum на зразок нижче, який за замовчуванням int . Будь ласка, додайте значення за замовчуванням спочатку вашого перерахунку. Застосовується у помічниках, коли не знайдено відповідності з вхідним значенням.

public enum FriendType  
{
    Default,
    Audio,
    Video,
    Image
}

public static class EnumHelper<T>
{
    public static T ConvertToEnum(dynamic value)
    {
        var result = default(T);
        var tempType = 0;

        //see Note below
        if (value != null &&
            int.TryParse(value.ToString(), out  tempType) && 
            Enum.IsDefined(typeof(T), tempType))
        {
            result = (T)Enum.ToObject(typeof(T), tempType); 
        }
        return result;
    }
}

NB: Тут я намагаюся проаналізувати значення на int, тому що enum за замовчуванням int Якщо ви визначаєте enum, як цей, який є тип байта .

public enum MediaType : byte
{
    Default,
    Audio,
    Video,
    Image
} 

Вам потрібно змінити синтаксичний аналіз на хелперний метод

int.TryParse(value.ToString(), out  tempType)

до

byte.TryParse(value.ToString(), out tempType)

Я перевіряю свій метод на наступні введення

EnumHelper<FriendType>.ConvertToEnum(null);
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("-1");
EnumHelper<FriendType>.ConvertToEnum("6");
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("2");
EnumHelper<FriendType>.ConvertToEnum(-1);
EnumHelper<FriendType>.ConvertToEnum(0);
EnumHelper<FriendType>.ConvertToEnum(1);
EnumHelper<FriendType>.ConvertToEnum(9);

Вибачте за мою англійську


8

Ось метод розширення , який кидає Int32в Enum.

Він шанує бітові прапори навіть тоді, коли значення вище максимально можливого. Наприклад, якщо у вас є перерахунок з можливостями 1 , 2 і 4 , але int дорівнює 9 , він розуміє, що як 1 за відсутності 8 . Це дозволяє оновлювати дані до оновлення коду.

   public static TEnum ToEnum<TEnum>(this int val) where TEnum : struct, IComparable, IFormattable, IConvertible
    {
        if (!typeof(TEnum).IsEnum)
        {
            return default(TEnum);
        }

        if (Enum.IsDefined(typeof(TEnum), val))
        {//if a straightforward single value, return that
            return (TEnum)Enum.ToObject(typeof(TEnum), val);
        }

        var candidates = Enum
            .GetValues(typeof(TEnum))
            .Cast<int>()
            .ToList();

        var isBitwise = candidates
            .Select((n, i) => {
                if (i < 2) return n == 0 || n == 1;
                return n / 2 == candidates[i - 1];
            })
            .All(y => y);

        var maxPossible = candidates.Sum();

        if (
            Enum.TryParse(val.ToString(), out TEnum asEnum)
            && (val <= maxPossible || !isBitwise)
        ){//if it can be parsed as a bitwise enum with multiple flags,
          //or is not bitwise, return the result of TryParse
            return asEnum;
        }

        //If the value is higher than all possible combinations,
        //remove the high imaginary values not accounted for in the enum
        var excess = Enumerable
            .Range(0, 32)
            .Select(n => (int)Math.Pow(2, n))
            .Where(n => n <= val && n > 0 && !candidates.Contains(n))
            .Sum();

        return Enum.TryParse((val - excess).ToString(), out asEnum) ? asEnum : default(TEnum);
    }

6

простий і зрозумілий спосіб введення int до перерахунку в c #:

 public class Program
    {
        public enum Color : int
        {
            Blue = 0,
            Black = 1,
            Green = 2,
            Gray = 3,
            Yellow =4
        }

        public static void Main(string[] args)
        {
            //from string
            Console.WriteLine((Color) Enum.Parse(typeof(Color), "Green"));

            //from int
            Console.WriteLine((Color)2);

            //From number you can also
            Console.WriteLine((Color)Enum.ToObject(typeof(Color) ,2));
        }
    }

6

Ви просто використовуєте Явне перетворення Cast int для перерахунку або перерахування до int

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine((int)Number.three); //Output=3

        Console.WriteLine((Number)3);// Outout three
        Console.Read();
    }

    public enum Number
    {
        Zero = 0,
        One = 1,
        Two = 2,
        three = 3
    }
}

4
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace SamplePrograme
{
    public class Program
    {
        public enum Suit : int
        {
            Spades = 0,
            Hearts = 1,
            Clubs = 2,
            Diamonds = 3
        }

        public static void Main(string[] args)
        {
            //from string
            Console.WriteLine((Suit) Enum.Parse(typeof(Suit), "Clubs"));

            //from int
            Console.WriteLine((Suit)1);

            //From number you can also
            Console.WriteLine((Suit)Enum.ToObject(typeof(Suit) ,1));
        }
    }
}

3

Вам просто подобається нижче:

int intToCast = 1;
TargetEnum f = (TargetEnum) intToCast ;

Щоб переконатися в тому, що ви призначаєте лише правильні значення та ви можете викинути виняток інакше:

int intToCast = 1;
if (Enum.IsDefined(typeof(TargetEnum), intToCast ))
{
    TargetEnum target = (TargetEnum)intToCast ;
}
else
{
   // Throw your exception.
}

Зауважте, що використання IsDefined коштує дорого і навіть більше, ніж просто кастинг, тому вирішити використовувати його чи ні залежить від вашої реалізації.


3

Можна використовувати метод розширення.

public static class Extensions
{

    public static T ToEnum<T>(this string data) where T : struct
    {
        if (!Enum.TryParse(data, true, out T enumVariable))
        {
            if (Enum.IsDefined(typeof(T), enumVariable))
            {
                return enumVariable;
            }
        }

        return default;
    }

    public static T ToEnum<T>(this int data) where T : struct
    {
        return (T)Enum.ToObject(typeof(T), data);
    }
}

використовувати, як нижче код

перерахувати:

public enum DaysOfWeeks
{
    Monday = 1,
    Tuesday = 2,
    Wednesday = 3,
    Thursday = 4,
    Friday = 5,
    Saturday = 6,
    Sunday = 7,
}

Використання:

 string Monday = "Mon";
 int Wednesday = 3;
 var Mon = Monday.ToEnum<DaysOfWeeks>();
 var Wed = Wednesday.ToEnum<DaysOfWeeks>();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.