Cast int для перечисления в C#


2,410

Как можно сделать int на enum в C#?

+28

Для наоборот: [получить-INT-значение-из-перечисление] (http://stackoverflow.com/questions/943398/get-int-value-from-enum) 09 июн. 132013-06-09 11:53:29

+3

Вы можете найти [этот пост на C# перечислениях] (http://www.codeducky.org/ins-outs-c-enums/) 20 июл. 142014-07-20 19:49:43

  0

Бесплатное видео 5 минут, охватывающее лучший из ответов ниже: http://app.deviq.com/courses/how-do-i-convert-int-to-enum-in-c-sharp 18 янв. 182018-01-18 18:31:32

2,944

Из строки:

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

Update:

Из номера можно также

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

Правильно это должно быть: YourEnum foo = (YourEnum) Enum.Parse (typeof (YourEnum), yourString) ИЛИ YourEnum foo = (YourEnum) Enum.Parse (typeof (YourEnum), yourInt) - применимо. 24 ноя. 112011-11-24 07:24:42

+15

@FlySwat, что, если 'YourEnum' является динамическим и будет известен только во время выполнения, и я хочу преобразовать в' Enum'? 19 фев. 122012-02-19 09:56:20

+1

@Shimmy. Если перечисление известно только во время выполнения, держите его динамическим. Тип безопасности (сильный ввод) может быть гарантирован только компилятором. Вы не можете сильно набирать объект во время выполнения. Ближе всего вы можете прийти к нему с помощью дженериков, но общий тип должен быть известен во время компиляции. 'T ToEnum <T> (int x) {return (T) x; } ', но нет реального преимущества перед литьем напрямую. 21 фев. 132013-02-21 15:40:35

  0

Быстрый вопрос, если вы вернетесь с 'YourEnum foo' до типа' int anInt': 'anInt = (int) foo;' это сработает? 13 апр. 132013-04-13 09:24:50

+1

@Logan Конечно, он работает. (_If_ базовый целочисленный тип перечисления не является 'int', вместо этого применяется к этому базовому целочисленному типу. Но крайне редко, что базовый тип должен быть чем-то другим, чем просто' int'.) 15 апр. 132013-04-15 18:05:37

+165

Имейте в виду, что Enum.Parse НЕ будет работать, если ваш код запутан. Во время выполнения после обфускации строка сравнивается с именами перечислений, и в этот момент имена перечислений не то, что вы ожидаете от них. В результате ваш синтаксический анализ завершится неудачей, когда в результате они преуспели. 26 апр. 132013-04-26 18:03:41

+96

** BEWARE ** Если вы используете синтаксис «из строки» выше и передаете недопустимую строку, которая является числом (например, «2342342» - если это не значение вашего перечисления), это фактически позволит это без бросая ошибку! Ваше перечисление будет иметь это значение (2342342), хотя это не является правильным выбором в самом перечислении. 25 июн. 132013-06-25 15:14:30

+82

Я думаю, что этот ответ немного устарел. Для строки вы действительно должны использовать 'var result = Enum.TryParse (yourString, out yourEnum)' nowadays (и проверять результат, чтобы определить, завершилось ли преобразование). 26 ноя. 132013-11-26 21:40:18

+4

@ JustinTConroy Я не знаю, согласен ли я с этим. В моих программах, если преобразование завершается неудачно, это часто является ошибкой, не подлежащей восстановлению, поэтому я хочу, чтобы исключение было выбрано. 01 фев. 142014-02-01 00:02:14

+2

Функция Parse представляет собой классический пример неприятного исключения. То есть исключение, которое бросается в совершенно не исключительное обстоятельство, обычно из-за неудачного дизайнерского решения. Разработчики C# признали этот неудачный дизайн, а позже добавили TryParse, чтобы справиться с этим. TryParse возвращает логическое значение, указывающее, удалось ли выполнить синтаксический анализ или не удалось, поэтому вы должны использовать этот логический объект вместо обработчика исключений. Дополнительную информацию см. В блоге Эрика Липперта о досадных исключениях (http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx). 03 фев. 142014-02-03 17:28:06

+14

Также возможно, что 'Enum.Parse' не учитывает регистр, добавив к вызову значение параметра' true': 'YourEnum foo = (YourEnum) Enum.Parse (typeof (YourEnum), yourString, true);' 05 фев. 142014-02-05 12:18:53

  0

Возможно ли, что преобразование из int работает, даже если значение int отсутствует в перечислении? Я просто попробовал его в .net 3.5 и, похоже, работает, что довольно запутанно. 07 окт. 142014-10-07 10:31:14

+1

Enum.ToObject был тем, что я искал. Это именно то, что вам нужно при работе с перечислениями динамически, и у вас есть тип, который, как вам известно, является перечислением, но не может доказать это компилятору, что не позволит вам отбрасывать из значения int произвольному типу. 08 дек. 142014-12-08 19:10:55

+6

@Santhos Да, существует 'Enum.IsDefined()', чтобы проверить, существует ли значение, которое вы хотите преобразовать, в вашем перечислении. 06 мар. 152015-03-06 10:37:08

+1

Хороший ответ. Просто заставляет меня задаться вопросом, почему этот язык высокого уровня требует так много для вещей, которые, естественно, намного проще на языках предшественников. В Visual Basic 6 вы можете пропустить значение int ИЛИ перечисление. Сравнивая с другими современными языками, даже PHP позволяет напрямую передавать int. 08 июл. 152015-07-08 04:50:23

+3

@JustinTConroy За исключением того, что это не так. Когда вы вызываете 'Parse', вы доверяете правильному входному значению, а когда это не так, это ошибка в коде (и есть исключение, которое должно быть). Если вы имеете дело с пользовательским вводом, вы всегда должны вызывать 'TryParse', потому что неверный ввод не является исключительным. В статье, которую вы упомянули, упоминается в «примере использования 99% для этого метода, это преобразование строк, вводимых пользователем», это ошибка, метод не предназначен для обработки пользовательского ввода, «TryParse». 17 авг. 152015-08-17 16:09:20

  0

@Aidiakapi Как часто вы пытаетесь разобрать строки в ints, где вы полностью контролируете переданное значение на всю вечность? ;-) 18 авг. 152015-08-18 17:28:26

+1

@JustinTConroy Каждый раз, когда вы доверяете вводу. Одним из примеров может быть сериализация или сохранение файлов. Вы можете доверять формату своего файла, чтобы быть правильным, если нет, просто выбросьте исключение, потому что в любом случае вы имеете дело с коррумпированным вводом. Большинство случаев связаны с совместимостью или совместимостью.Всякий раз, когда вы общаетесь между программами, использующими ints, хранящиеся в виде строк, исключение происходит из-за недопонимания и указывает на ошибку в коде. 18 авг. 152015-08-18 18:25:54

+1

Вот скрипка или REPL, чтобы возиться с этим примером https://repl.it/EJCV/1 28 окт. 162016-10-28 19:06:23


83

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

int one = 1; 
MyEnum e = (MyEnum)one; 

681

Просто брось:

MyEnum e = (MyEnum)3; 

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

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

Опасайтесь, вы не можете использовать Enum.IsDefined, если вы используете атрибут Flags, а значение представляет собой комбинацию флагов, например : Keys.L | Keys.Control 31 июл. 092009-07-31 04:49:58

+10

Что касается 'Enum.IsDefined', имейте в виду, что это может быть опасно: http://msdn.microsoft.com/en-us/library/ms229025(VS.90).aspx 04 дек. 132013-12-04 11:26:37

  0

С другой стороны, если Я проверяю ввод на основе перечисления, предоставляемого библиотекой, перед отправкой в ​​библиотеку ... 23 апр. 142014-04-23 16:06:30

  0

Я предпочитаю это определение: ** «Возвращает указание, существует ли константа с указанным значением в указанной перечислении» ** из [MSDN] (http://msdn.microsoft.com/en-us/library/system.enum.isdefined (v = vs.110) .aspx) 18 авг. 142014-08-18 19:13:59

+1

... Поскольку ваше определение может вводить в заблуждение, потому что вы говорите : ** «... проверьте, находится ли он в диапазоне ...» **, который подразумевает в пределах диапазона чисел с начальными и конечными пределами ... 18 авг. 142014-08-18 19:20:33


21

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

var MyEnumType = typeof(MyEnumType); 

Тогда:

Enum.ToObject(typeof(MyEnum), 3) 

43

Ниже хороший класс утилита для Перечисления

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

25

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

for (var flagIterator = 0x1; flagIterator <= 0x80000000; flagIterator <<= 1) 
{ 
    // Check to see if the current flag exists in the bit mask 
    if ((intValue & flagIterator) != 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), flagIterator)) 
      ListOfEnumValues.Add((MyEnum)flagIterator); 
    } 
} 

52

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

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

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

  0

Не работает с перечислениями флагов 30 мар. 152015-03-30 10:09:23

+1

это хорошо. я был удивлен, что не исключение, когда вы делаете недопустимое значение для перечисления с поддержкой int-backed. 20 ноя. 152015-11-20 00:50:52

  0

На самом деле это не так сильно отличается от ответа с наивысшим рейтингом. В этом ответе также обсуждается использование Enum.IsDefined после того, как вы передали строку в тип Enum. Поэтому даже если строка была выполнена без ошибок, Enum.IsDefined все равно поймает ее 20 дек. 172017-12-20 16:17:13


37

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

+16

Это полезно при преобразовании из строки. Но не при преобразовании из int. 01 ноя. 112011-11-01 15:08:35


182

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

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, которая позволяет вам указать, что сравнение нечувствительно к регистру (т.е. пользователь, набрав «красный» (строчный), мог бы сбой вышеуказанного кода без этого изменение.) 04 июн. 132013-06-04 20:56:56

+21

Прохладный, кроме этого это не вопрос. 08 июн. 132013-06-08 21:41:41

+5

Удобный, но вопрос конкретно спрашивает о ints. 27 май. 152015-05-27 10:18:34

+1

это также работает, если строка является целым числом, например. «2» 06 окт. 162016-10-06 19:19:18

+1

Это вызовет исключение, если enumString имеет значение null (вчера был аналогичный вопрос). Попробуйте использовать TryParse вместо Parse. TryParse также проверяет, является ли T типом Enum 18 окт. 162016-10-18 15:03:33


37

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

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

Это не работает с перечислениями флагов 30 мар. 152015-03-30 10:00:59


4

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


} 
} 

16

enter image description here

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

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

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

104

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

Как материал работает

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

public enum Foo : short 

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

Если посмотреть на это с точки IL зрения, (нормальный, целое) перечисление выглядит следующим образом:

.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(); 
} 
+7

Я понимаю, что это старый пост, но как вы получаете этот уровень знаний в C#? Это от чтения через спецификацию C#? 15 ноя. 152015-11-15 00:19:15

+13

@ Rolan Я иногда хочу, чтобы больше людей спрашивали об этом. :-) Честно говоря, я действительно не знаю; Я пытаюсь понять, как все работает и получает информацию, где бы я ни смог ее получить. Я прочитал стандарт C#, но я также регулярно декомпилирую код с Reflector (я даже много разбираюсь в коде ассемблера x86) и делаю массу небольших экспериментов. Кроме того, в этом случае помогает знание других языков; Я занимаюсь CS уже около 30 лет, и в какой-то момент некоторые вещи становятся «логическими» - f.ex. перечисление должно быть целым, потому что в противном случае прерывание будет прерываться (или ваша производительность будет снижаться). 15 ноя. 152015-11-15 11:38:42

+6

Я считаю, что ключ к правильной разработке программного обеспечения - это знание того, как работает материал. Для меня это означает, что если вы пишете фрагмент кода, вы знаете, как он грубо переводится на f.ex. операции с процессором и выборки/записи в памяти. Если вы спросите, как добраться до этого уровня, я бы предложил построить тонну небольших тестовых примеров, делая их более жесткими, когда вы идете, каждый раз пытаетесь предсказать результат и затем тестировать их (включая декомпиляцию и т. Д.). После выяснения всех деталей и всех характеристик вы можете проверить, правильно ли вы получили это (тупой) стандарт. По крайней мере, это будет мой подход. 15 ноя. 152015-11-15 11:43:46

  0

Фантастический ответ, спасибо! В последнем примере кода он генерирует исключение во время выполнения, потому что o - объект. Вы можете указать переменную int до короткой, если она попадает в короткий диапазон. 11 авг. 162016-08-11 17:04:35

  0

@gravidThoughts Спасибо. На самом деле это операция unboxing, поэтому она не будет делать никаких неявных преобразований, как те, которые вы описываете. Кастинг иногда запутывается на C#, если вы не знаете подробностей ... Во всяком случае, потому что 'int'! =' Short', он будет бросать (unboxing терпит неудачу). Если вы выполняете 'object o = (short) 5;', он будет работать, потому что тогда будут совпадать типы. Речь идет не о диапазоне, а о типе. 12 авг. 162016-08-12 06:43:14

  0

@atlaste, если 'MyEnum' выводит (или это?) Из' int', почему назначение значения int для типизированной переменной MyEnum не работает без явного приведения? Можно ли каким-то образом выполнить задание без явного приведения? 04 янв. 182018-01-04 11:27:48

  0

@HeyJude Ну, это просто потому, что команда разработчиков C# решила, что это правильный синтаксис. Это в основном позволяет избежать перезаписи enum с неопределенными целыми значениями (например, в противном случае вы можете установить любое перечисление на любое значение). На других языках, таких как C++, это действительно возможно. 04 янв. 182018-01-04 11:30:30


7

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

14

Слегка деться от первоначального вопроса, но я нашел an answer to Stack Overflow question Get int value from 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; 
} 

Очевидно, что некоторые функции типа перечисления будут потеряны, но для хранения кучу постоянных идентификаторов базы данных, это кажется довольно аккуратный решение.

+3

перечисления заменяли использование целочисленных констант, подобных этому, поскольку они обеспечивают большую безопасность типов. 01 сен. 142014-09-01 07:41:58

+1

Paul, это метод сбора связанных между собой int-констант (например, констант идентификатора базы данных), поэтому их можно использовать напрямую, не прикладывая их к int каждый раз они используются. Их тип * является * целым числом, а не, например, DatabaseIdsEnum. 01 сен. 142014-09-01 09:37:34

+1

Существует, по крайней мере, одна ситуация, в которой я обнаружил, что безопасность типа перечисления может быть непреднамеренно обойдена. 10 сен. 142014-09-10 17:33:38


10

Это разделяет целые числа или строки на целевое перечисление с частичным согласованием в 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; 
       } 
      } 
     } 
    } 
} 

FYI: Вопрос был о целых числах, которые никто не упомянул также явно преобразовать в Enum.TryParse()


10

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

enum Importance 
{} 

Importance importance; 

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

Вопрос конкретно задает вопрос о целых числах. 27 май. 152015-05-27 10:13:30

+2

Will Yu, пожалуйста, отредактируйте свой ответ, чтобы все знали, что Enum.TryParse будет работать над строкой значения или имени переименования (я не удержался) 10 фев. 162016-02-10 05:37:55

  0

Джереми, Вейр, работающий над этим (не смог устоять). 29 янв. 182018-01-29 12:20:05


14

Вы находитесь в флагов перечислению осведомленный безопасный метод новообращенного:

public static bool TryConvertToEnum<T>(this int instance, out T result) 
    where T: struct 
{ 
    var enumType = typeof (T); 
    if (!enumType.IsEnum) 
    { 
    throw new ArgumentException("The generic type must be an enum."); 
    } 
    var success = Enum.IsDefined(enumType, instance); 
    if (success) 
    { 
    result = (T)Enum.ToObject(enumType, instance); 
    } 
    else 
    { 
    result = default(T); 
    } 
    return success; 
} 

5

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

4

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

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

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


7

После немного лучший метод расширения

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