Как я могу привести int к enum?

Как можно преобразовать int в enum в C #?


person lomaxx    schedule 27.08.2008    source источник


Ответы (31)


Из int:

YourEnum foo = (YourEnum)yourInt;

Из строки:

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.")
}

Обновление:

С номера вы также можете

YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);
person FlySwat    schedule 27.08.2008
comment
Это должно быть правильно: YourEnum foo = (YourEnum) Enum.Parse (typeof (YourEnum), yourString) ИЛИ YourEnum foo = (YourEnum) Enum.Parse (typeof (YourEnum), yourInt) - в зависимости от обстоятельств. - person Tathagat Verma; 24.11.2011
comment
@FlySwat, что, если YourEnum является динамическим и будет известен только во время выполнения, а я хочу преобразовать в Enum? - person Shimmy Weitzhandler; 19.02.2012
comment
@ Шимми. Если перечисление известно только во время выполнения, сохраните его динамическим. Безопасность типов (строгая типизация) в любом случае может гарантировать только компилятор. Вы не можете строго вводить объект во время выполнения. Ближе всего к этому можно подойти с помощью универсальных типов, но универсальный тип должен быть известен во время компиляции. T ToEnum<T>(int x) { return (T)x; } но нет никакого реального преимущества перед кастингом напрямую. - person Olivier Jacot-Descombes; 21.02.2013
comment
Быстрый вопрос: если вы вернетесь с YourEnum foo на int anInt введите: anInt = (int)foo;, это сработает? - person Logan; 13.04.2013
comment
@Logan Конечно, работает. (Если базовый целочисленный тип перечисления не int, вместо этого приведите его к этому базовому целочисленному типу. Но очень редко базовым типом должно быть что-то иное, чем просто int.) - person Jeppe Stig Nielsen; 15.04.2013
comment
Имейте в виду, что Enum.Parse НЕ будет работать, если ваш код запутан. Во время выполнения после обфускации строка сравнивается с именами перечислений, и на этом этапе имена перечислений не такие, как вы ожидаете. В результате ваш синтаксический анализ потерпит неудачу там, где он преуспел раньше. - person jropella; 26.04.2013
comment
ОСТОРОЖНО Если вы используете синтаксис строки from выше и передаете недопустимую строку, которая является числом (например, 2342342 - при условии, что это не значение вашего перечисления), это фактически разрешит, не бросая ошибка! Ваше перечисление будет иметь это значение (2342342), даже если оно не является допустимым выбором в самом перечислении. - person JoeCool; 25.06.2013
comment
Я думаю, что этот ответ сейчас немного устарел. Для строки вы действительно должны использовать var result = Enum.TryParse(yourString, out yourEnum) в настоящее время (и проверять результат, чтобы определить, не удалось ли преобразовать). - person Justin T Conroy; 27.11.2013
comment
@JustinTConroy Не знаю, согласен ли я с этим. В моих программах, если преобразование не удается, это часто неисправимая ошибка, поэтому я хочу, чтобы было создано исключение. - person jackvsworld; 01.02.2014
comment
Функция Parse представляет собой классический пример неприятного исключения. То есть исключение, которое возникает в совершенно неисключительных обстоятельствах, обычно из-за неудачного дизайнерского решения. Разработчики C # признали этот неудачный дизайн и позже добавили TryParse для решения этой проблемы. TryParse возвращает логическое значение, которое указывает, был ли синтаксический анализ успешным или неудачным, поэтому вы должны использовать это логическое значение вместо обработчика исключений. См. Сообщение в блоге Эрика Липперта о досадных исключениях для получения дополнительной информации. - person Justin T Conroy; 03.02.2014
comment
Также можно сделать Enum.Parse нечувствительным к регистру, добавив к вызову true значение параметра: YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString, true); - person Erik Schierboom; 05.02.2014
comment
Возможно ли, что преобразование из int работает, даже если значение int отсутствует в перечислении? Я просто попробовал это в .net 3.5, и, похоже, он работает, что довольно сбивает с толку. - person Santhos; 07.10.2014
comment
Enum.ToObject - это то, что я искал. Это именно то, что вам нужно при динамической работе с перечислениями, и у вас есть тип, который, как вы знаете, является перечислением, но не можете доказать это компилятору, что не позволит вам выполнить приведение из значения int к произвольному типу. - person Colin; 08.12.2014
comment
@Santhos Да, есть Enum.IsDefined(), чтобы проверить, существует ли значение, которое вы хотите преобразовать, в вашем перечислении. - person Thaoden; 06.03.2015
comment
@JustinTConroy За исключением того, что это не так. Когда вы вызываете Parse, вы доверяете правильности входного значения, а когда это не так, это ошибка в коде (и там должно быть исключение). Если вы имеете дело с пользовательским вводом, вы всегда должны вызывать TryParse, потому что недопустимый ввод не является исключением. В статье, которую вы связали, упоминается, что в 99% случаев использования этого метода является преобразование строк, вводимых пользователем, это ошибка, метод не предназначен для обработки пользовательского ввода, TryParse. - person Aidiakapi; 17.08.2015

Просто примените это:

MyEnum e = (MyEnum)3;

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

if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }
person Matt Hamilton    schedule 27.08.2008
comment
Помните, что вы не можете использовать Enum.IsDefined, если вы используете атрибут Flags, а значение представляет собой комбинацию флагов, например: Keys.L | Ключи.Контроль - person dtroy; 31.07.2009
comment
Что касается Enum.IsDefined, имейте в виду, что это может быть опасно: msdn. microsoft.com/en-us/library/ms229025(VS.90).aspx - person adrian; 04.12.2013
comment
Я предпочитаю это определение: Возвращает указание, существует ли константа с указанным значением в указанном перечислении из MSDN - person Pap; 18.08.2014
comment
... Потому что ваше определение может вводить в заблуждение, потому что вы говорите: ... проверьте, находится ли он в диапазоне ..., что подразумевает наличие диапазона чисел с начальным и конечным пределами ... - person Pap; 18.08.2014
comment
Обратите внимание, что значение Enum по умолчанию - int, но его можно изменить, что может сделать приведение опасным. Проверьте ответ @atlastes. - person daniloquio; 04.04.2018
comment
@adrian, можешь ли ты дать краткий пример опасного сценария? С трудом оборачиваюсь вокруг этого документа. - person Michael Crenshaw; 01.11.2018

В качестве альтернативы используйте метод расширения вместо однострочного:

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

Использование:

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

OR

string color = "Red";
var colorEnum = color.ToEnum<Color>();
person Abdul Munim    schedule 11.11.2011
comment
Для обработки пользовательского ввода, вероятно, будет хорошей идеей вызвать перегрузку Enum.Parse, которая позволяет указать, что сравнение НЕ будет чувствительным к регистру (т.е. пользователь, вводящий красный (нижний регистр), приведет к сбою приведенного выше кода без этого изменения). - person BrainSlugs83; 05.06.2013
comment
Удобно, но вопрос конкретно про ints. - person BJury; 27.05.2015
comment
это также работает, если строка является целым числом, например. 2 - person TruthOf42; 06.10.2016
comment
Это вызовет исключение, если enumString имеет значение null (вчера была аналогичная проблема). Рассмотрите возможность использования TryParse вместо Parse. TryParse также проверит, является ли T типом Enum - person Justin; 18.10.2016
comment
Этот тип метода расширения на System.String выглядит как загрязнение пространства имен - person Mr Anderson; 13.05.2019
comment
В последней версии C # /. NET вы можете использовать E вместо T, чтобы вы были уверены, что метод вызывается в классе Enum - person Jimi; 13.12.2019

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

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

int one = 1;
MyEnum e = (MyEnum)one;
person abigblackman    schedule 27.08.2008

Я использую этот фрагмент кода для преобразования int в свое перечисление:

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

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

person MSkuta    schedule 21.10.2011
comment
это хорошо. я был удивлен, что нет исключения при приведении недопустимого значения в перечисление с поддержкой int. - person orion elenzil; 20.11.2015
comment
На самом деле это не так уж и отличается от самого популярного ответа. В этом ответе также обсуждается использование Enum.IsDefined после преобразования строки в тип Enum. Таким образом, даже если строка была введена без ошибок, Enum.IsDefined все равно ее поймает. - person Don Cheadle; 20.12.2017

Ниже приведен хороший служебный класс для 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;
    }
}
person Tawani    schedule 07.09.2010

Для числовых значений это безопаснее, поскольку он вернет объект независимо от того, что:

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;
    }
}
person Sébastien Duval    schedule 21.02.2013
comment
Вы возвращаете значение по умолчанию (T), если оно не определено. Как это помогает идентифицировать неопределенные? - person Ε Г И І И О; 11.09.2020

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

person Ryan Russon    schedule 01.11.2011
comment
Это полезно при преобразовании из строки. Но не при преобразовании из int. - person CodesInChaos; 01.11.2011

Если у вас есть целое число, которое действует как битовая маска и может представлять одно или несколько значений в перечислении [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())

person Evan M    schedule 13.04.2011

Иногда бывает объект типа MyEnum. Нравиться

var MyEnumType = typeof(MyEnum);

Потом:

Enum.ToObject(typeof(MyEnum), 3)
person L. D.    schedule 02.07.2010

Это метод безопасного преобразования с учетом перечисления флагов:

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;
}
person Daniel Fisher lennybacon    schedule 30.03.2015
comment
Теперь это можно улучшить с помощью C # 7.3, ограничив Enum вместо struct, что означает, что нам не нужно полагаться на проверку времени выполнения! - person Scott; 09.11.2018

Слегка уйдя от исходного вопроса, я нашел ответ на вопрос о переполнении стека Получить значение int из перечисления < / a> полезно. Создайте статический класс со свойствами 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 будут потеряны, но для хранения множества констант идентификаторов базы данных это кажется довольно аккуратным решением.

person Ted    schedule 17.07.2014
comment
перечисления заменили использование таких целочисленных констант, поскольку они обеспечивают большую безопасность типов - person Paul Richards; 01.09.2014
comment
Пол, это метод сбора связанных констант int (например, констант идентификатора базы данных), чтобы их можно было использовать напрямую, без необходимости приводить их к int каждый раз, когда они используются. Их тип - целое число, например, не DatabaseIdsEnum. - person Ted; 01.09.2014
comment
Я обнаружил по крайней мере одну ситуацию, в которой можно непреднамеренно обойти безопасность перечислимого типа. - person Thierry; 10.09.2014
comment
Но перечисления также гарантируют, что все значения уникальны, чего в этом подходе также нет. - person derHugo; 11.10.2019

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

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

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

MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");
person Shivprasad Koirala    schedule 05.02.2014

Ниже приведен немного лучший метод расширения:

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;
}
person Kamran Shahid    schedule 16.12.2016
comment
на самом деле это намного лучше, потому что, если значение int не является определенной записью в перечислении, вы можете использовать оператор else, чтобы установить enumString в значение по умолчанию. Спасибо - person NDUF; 27.01.2021

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

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

person CZahrobsky    schedule 30.07.2014

Из строки: (Enum.Parse устарел, используйте Enum.TryParse)

enum Importance
{}

Importance importance;

if (Enum.TryParse(value, out importance))
{
}
person Will Yu    schedule 21.11.2014
comment
Вопрос конкретно касается целых чисел. - person BJury; 27.05.2015
comment
Юй, пожалуйста, отредактируйте свой ответ, чтобы все знали, что Enum.TryParse будет работать со строкой значения или имени перечисления (я не мог устоять) - person JeremyWeir; 10.02.2016
comment
Джереми, Вейр работает над этим (тоже не удержался). - person huysentruitw; 29.01.2018

Для большей надежности вам следует предусмотреть релаксацию соответствия типов.

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();
}
person Community    schedule 02.07.2019
comment
Это хороший ответ. Жаль, что в данный момент это так далеко на странице! - person MikeBeaton; 20.02.2020

Вот метод расширения, который преобразует 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);
    }
person Chad Hedgcock    schedule 22.02.2019

В моем случае мне нужно было вернуть перечисление из службы 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>();
person LawMan    schedule 02.07.2014

Это может помочь вам преобразовать любые входные данные в желаемое пользователем перечисление. Предположим, у вас есть перечисление, подобное приведенному ниже, которое по умолчанию 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;
    }
}

N.B: Здесь я пытаюсь преобразовать значение в int, потому что enum по умолчанию - int, если вы определяете enum, как это, которое имеет тип byte.

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

Вам нужно изменить синтаксический анализ вспомогательного метода с

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

to

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

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

person reza.cse08    schedule 17.11.2016

Простой и понятный способ преобразования 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));
    }
}
person Mohammad Aziz Nabizada    schedule 08.12.2018

Различные способы трансляции туда и обратно 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);


 }
}
person gmail user    schedule 08.01.2014

Я больше не знаю, где я беру часть этого расширения перечисления, но это из 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;
person Franki1986    schedule 07.01.2016

Вы просто используете Явное преобразование. Преобразование 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
    }
}
person Shivam Mishra    schedule 01.02.2019

Просто сделайте так, как показано ниже:

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 является дорогостоящим и даже большим, чем просто приведение типов, поэтому решение использовать его или нет зависит от вашей реализации.

person Mselmi Ali    schedule 27.07.2019

Просто вы можете привести int к enum

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

    var day= (DaysOfWeeks)5;
    Console.WriteLine("Day is : {0}", day);
    Console.ReadLine();
person Inam Abbas    schedule 10.06.2020
comment
Если бы приведение работало, вы не смогли бы сохранить его как int. - person QWERTY; 19.06.2020
comment
Пожалуйста, попробуйте понять int до Enum, я думаю, что это ответ, который вам поможет. - person Inam Abbas; 23.06.2020

Вы можете использовать метод расширения.

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>();
person Reza Jenabi    schedule 24.04.2020

Мне нужны две инструкции:

YourEnum possibleEnum = (YourEnum)value; // There isn't any guarantee that it is part of the enum
if (Enum.IsDefined(typeof(YourEnum), possibleEnum))
{
    // Value exists in YourEnum
}
person Cesar Alvarado Diaz    schedule 18.06.2020

var result = Enum.TryParse(yourString, out yourEnum) 

И обязательно проверьте результат, чтобы определить, не удалось ли выполнить преобразование.

person Shah Zaiƞ    schedule 23.09.2020

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

var enumValue = (MyEnum?)enumInt;

if (!enumValue.HasValue)
{
    throw new ArgumentException(nameof(enumValue));
}
person Alexander    schedule 04.02.2021