21 ответов:
из строки:
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);
просто бросьте его:
MyEnum e = (MyEnum)3;вы можете проверить, если он находится в диапазоне с помощью перечисление.Т. е.:
if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }
альтернативно, используйте метод расширения вместо однострочного:
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>();
Я думаю, чтобы получить полный ответ, люди должны знать, как перечисления работают внутри .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(); }
Я использую этот кусок кода, чтобы привести int к моему перечислению:
if (typeof(YourEnum).IsEnumDefined(valueToCast)) return (YourEnum)valueToCast; else { //handle it here, if its not defined }Я считаю это лучшим решением.
Ниже приведен хороший класс полезности для перечислений
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; } }
Если вы готовы к 4.0 .NET Framework, есть новый перечисление.TryParse () функция, которая очень полезна и хорошо играет с атрибутом [Flags]. Смотрите перечисление.Метод TryParse (String, TEnum%)
для числовых значений это безопаснее, так как он будет возвращать объект независимо от того, что:
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; } }
если у вас есть целое число, которое действует как битовая маска и может представлять одно или несколько значений в перечислении [Flags], вы можете использовать этот код для разбора отдельных значений флага в список:
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); } }
иногда у вас есть объект
MyEnumтип. Какvar MyEnumType = typeof(MyEnumType);затем:
Enum.ToObject(typeof(MyEnum), 3)
это перечисление флагов известно безопасный метод преобразования:
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; }
для преобразования строки в int в enum или ПЕРЕЧИСЛИМОЙ константы мы должны использовать перечислимый.Функция разбора. Вот видео на youtubehttps://www.youtube.com/watch?v=4nhx4VwdRDk которые на самом деле демонстрируют со строкой и то же самое относится к int.
код идет, как показано ниже, где "красный" - это строка, а "MyColors" - это цветовое перечисление, которое имеет цветовые константы.
MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");
немного отойдя от первоначального вопроса, но я нашел ответ на вопрос переполнения стека получить значение int из перечисления полезное. Создайте статический класс с помощью
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; }очевидно, что некоторые функции типа перечисления будут потеряны, но для хранения множества констант идентификатора базы данных, это кажется довольно аккуратным решением.
это анализирует целые числа или строки для целевого перечисления с частичным совпадением в dot.NET 4.0 использование дженериков, как в классе утилиты Тавани выше. Я использую его для преобразования переменных переключателя командной строки, которые могут быть неполными. Поскольку перечисление не может быть null, вы должны логически указать значение по умолчанию. Его можно назвать так:
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: вопрос был о целых числах, которые никто не упомянул также будет явное преобразование в перечисление.TryParse ()
из строки: (перечисление.Разбор устарел, используйте перечисление.TryParse)
enum Importance {} Importance importance; if (Enum.TryParse(value, out importance)) { }
ниже немного лучше метод расширения
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; }
в моем случае мне нужно было вернуть перечисление из службы WCF. Мне также нужно было дружеское имя, а не только перечисление.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; } }вот метод расширения, который получает описание из перечисления.
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>();
различные способы бросания и
Enumenum 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); } }
Я больше не знаю, где я получаю часть этого расширения перечисления, но это из 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;
Это может помочь вам конвертировать любые входные данные в нужный пользователю перечисление. Предположим, у вас есть перечисление, как ниже которого по умолчанию int. Пожалуйста, добавьте по умолчанию значение сначала вашего перечисления. Который используется в helpers 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 Если вы определяете перечисление как это, которое является байт тип.
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);извините за мой английский

Comments