Как привести int к enum?

Ответы:

3795

Из строки:

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);
FlySwat
источник
31
@FlySwat, что, если YourEnumон динамический и будет известен только во время выполнения, и что я хочу преобразовать в Enum?
Шимми Вайцхандлер
226
Помните, что Enum.Parse НЕ будет работать, если ваш код запутан. Во время выполнения после запутывания строка сравнивается с именами перечислений, и в этот момент имена перечислений не соответствуют ожидаемым. Ваш анализ потерпит неудачу там, где они преуспели раньше, в результате.
jropella
159
ВНИМАНИЕ! Если вы используете приведенный выше синтаксис «из строки» и передаете недопустимую строку, которая является числом (например, «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
Пап
3
... Потому что ваше определение может вводить в заблуждение, потому что вы говорите: "... проверьте, находится ли оно в диапазоне ...", что подразумевает в пределах диапазона чисел с начальным и конечным пределами ...
Пап
3
@ mac9416 Я попытался привести краткий пример на gist.github.com/alowdon/f7354cda97bac70b44e1c04bc0991bcc - в основном, используя IsDefinedдля проверки входных значений, вы оставляете себя уязвимым для людей, добавляющих новые значения enum позже, которые будут проходить 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, которая позволяет указать, что сравнение НЕ чувствительно к регистру (т. Е. Пользователь, набрав «red» (нижний регистр), вылетит из приведенного выше кода без этого изменения). .)
BrainSlugs83
9
Удобно, но вопрос специально задает насчет целых.
БЮри
2
это также работает, если строка является целым числом, например, «2»
TruthOf42
2
Это вызовет исключение, если enumString имеет значение null (вчера была похожая проблема). Попробуйте использовать TryParse вместо Parse. TryParse также проверит, является ли T типом Enum
Джастин
Этот метод расширения System.Stringвыглядит как загрязнение пространства имен
г-н Андерсон
160

Я думаю, чтобы получить полный ответ, люди должны знать, как перечисления работают внутри .NET.

Как это работает

Перечисление в .NET - это структура, которая отображает набор значений (полей) в базовый тип (по умолчанию это int). Тем не менее, вы можете выбрать целочисленный тип, который будет отображаться в вашем перечислении:

public enum Foo : short

В этом случае перечисление отображается на short типом данных, что означает, что оно будет сохранено в памяти как короткое и будет вести себя как короткое, когда вы используете его.

Если вы посмотрите на это с точки зрения IL, перечисление (normal, int) выглядит так:

.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__хранятся отдельно от значений перечисления. В случае перечисления Fooвыше тип value__int16. По сути, это означает, что вы можете хранить в перечислении все, что хотите, при условии совпадения типов .

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

Ответ

Итак, если у вас есть целое число, которое вы хотите отобразить в перечисление, среда выполнения должна сделать только 2 вещи: скопировать 4 байта и назвать его как-нибудь иначе (имя перечисления). Копирование неявно, потому что данные хранятся как тип значения - это в основном означает, что если вы используете неуправляемый код, вы можете просто обмениваться перечислениями и целыми числами без копирования данных.

Чтобы сделать это безопасным, я думаю, что лучше всего знать, что базовые типы являются одинаковыми или неявно конвертируемыми, и гарантировать, что значения перечисления существуют (они не проверяются по умолчанию!).

Чтобы увидеть, как это работает, попробуйте следующий код:

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();
}
atlaste
источник
7
Я понимаю, что это старый пост, но как вы получаете этот уровень знаний в C #? Это от чтения спецификации C #?
Ролан
20
@Rolan Иногда я хочу, чтобы больше людей спрашивали об этом. :-) Если честно, я действительно не знаю; Я пытаюсь понять, как все работает, и получать информацию везде, где только могу. Я читал стандарт C #, но я также регулярно декомпилирую код с помощью Reflector (я даже много смотрю на код ассемблера x86) и провожу кучу маленьких экспериментов. Кроме того, знание других языков помогает в этом случае; Я занимаюсь CS уже около 30 лет, и в какой-то момент некоторые вещи становятся «логичными» - например. Перечисление должно быть целочисленным, потому что в противном случае взаимодействие будет нарушено (или ваша производительность снизится).
Атлас
9
Я считаю, что ключ к правильной разработке программного обеспечения - это знание того, как все работает. Для меня это означает, что если вы пишете кусок кода, вы знаете, как он примерно переводится в f.ex. Операции процессора и выборки / записи памяти. Если вы спросите, как добраться до этого уровня, я бы предложил создать тонну небольших тестовых случаев, сделать их более сложными по мере продвижения, каждый раз пытаться предсказать результат и проверять их впоследствии (в том числе декомпиляцию и т. Д.). После выяснения всех деталей и всех характеристик, вы можете проверить, правильно ли вы поняли (унылый) стандарт. По крайней мере, таков мой подход.
атлас
1
Фантастический ответ, спасибо! В вашем последнем примере кода он генерирует исключение во время выполнения, потому что o является объектом. Вы можете привести переменную типа int к короткому, если она попадает в короткий диапазон.
gravidThoughts
@gravidThoughts Спасибо. На самом деле это операция распаковки, поэтому она не будет выполнять никаких неявных преобразований, подобных описанным вами. В C # иногда происходит сбивание с толку, если вы не знаете подробностей ... Во всяком случае, потому что int! = short, Оно будет выброшено (распаковка не удалась). Если вы это сделаете object o = (short)5;, это будет работать, потому что тогда типы будут совпадать. Речь идет не о диапазоне, а о типе.
Атлас
121

Возьмите следующий пример:

int one = 1;
MyEnum e = (MyEnum)one;
abigblackman
источник
64

Я использую этот кусок кода, чтобы привести int к моему enum:

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

Я считаю это лучшим решением.

MSkuta
источник
1
это хорошо. Я был удивлен, что нет исключения при преобразовании недопустимого значения в перечисление с внутренней поддержкой.
Орион Элензил
Это на самом деле не так уж и отличается от самого популярного ответа. В этом ответе также обсуждается использование Enum.IsDefined после приведения строки к типу Enum. Таким образом, даже если строка была приведена без ошибок, Enum.IsDefined все равно ее поймает
Дон Чидл
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;
    }
}
Tawani
источник
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;
    }
}
Себастьян Дюваль
источник
Не работает для перечисления флагов
Сейед Мортеза Мусави
44

Если вы готовы к 4.0 .NET Framework, есть новая функция Enum.TryParse (), которая очень полезна и хорошо работает с атрибутом [Flags]. См. Enum.TryParse Method (String, TEnum%)

Райан Руссон
источник
21
Это полезно при конвертации из строки. Но не при конвертации из int.
CodesInChaos
35

Если у вас есть целое число, которое действует как битовая маска и может представлять одно или несколько значений в перечислении [Flags], вы можете использовать этот код для анализа значений отдельных флагов в списке:

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)
Эван М
27

Иногда у вас есть объект для MyEnumтипа. подобно

var MyEnumType = typeof(MyEnumType);

Затем:

Enum.ToObject(typeof(MyEnum), 3)
LD
источник
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. Вот видео на YouTube https://www.youtube.com/watch?v=4nhx4VwdRDk которое фактически демонстрирует со строкой и то же самое относится к int.

Код выглядит так, как показано ниже, где «red» - это строка, а «MyColors» - это цвет ENUM, который имеет цветовые константы.

MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");
Шивпрасад Койрала
источник
20

Немного отойдя от исходного вопроса, но я нашел ответ на вопрос переполнения стека. Полезно получить значение 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 (например, константы идентификатора базы данных), чтобы их можно было использовать напрямую, не приводя их к int каждый раз, когда они используются. Их тип является целым числом, а не, например, DatabaseIdsEnum.
Тед
1
Я обнаружил, по крайней мере, одну ситуацию, в которой безопасность типа enum может быть непреднамеренно обойдена.
Тьерри
Но перечисления также гарантируют, что все значения уникальны, чего также не хватает этому подходу
derHugo
15

Это анализирует целые числа или строки в целевом перечислении с частичным соответствием в dot.NET 4.0, используя обобщенные значения, как в классе утилит Tawani выше. Я использую его для преобразования переменных командной строки, которые могут быть неполными. Поскольку перечисление не может быть нулевым, вы должны логически указать значение по умолчанию. Это можно назвать так:

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;
                }
            }
        }
    }
}

К вашему сведению: вопрос был о целых числах, которые никто не упомянул, также будут явно конвертированы в Enum.TryParse ()

CZahrobsky
источник
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

В моем случае мне нужно было вернуть enum из службы 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;
    }
}

Вот метод Extension, который получает описание из 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;
Franki1986
источник
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);


 }
}
пользователь Gmail
источник
8

Это может помочь вам преобразовать любые входные данные в желаемое перечисление пользователя . Предположим, у вас есть перечисление как ниже, которое по умолчанию int . Пожалуйста, добавьте значение по умолчанию в начале вашего перечисления. Который используется у помощников medthod, когда не найдено совпадений с входным значением.

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);

Извините за мой английский

reza.cse08
источник
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 к enum в 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 в enum или enum в 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));
        }
    }
}
Aswal
источник
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);
    }
}

используйте как ниже код

enum:

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>();
Реза Дженаби
источник