Как можно привести int
к enum
в C#?
Из струны:
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;
Обновление:
С номера вы также можете
YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);
Просто бросьте его:
MyEnum e = (MyEnum)3;
Вы можете проверить, находится ли он в диапазоне, используя Enum.IsDefined:
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-это структура, которая отображает набор значений (полей) для основного типа (по умолчанию инт
). Однако, вы можете выбрать интегрального типа, что ваше перечисление карт:
public enum Foo : short
В этом случае перечисление сопоставляется с коротким
тип данных, который означает, что он будет храниться в памяти как короткий и будет вести себя как короткие, когда вы разыгрываете и использовать его.
Если вы посмотрите на это с Ил точки зрения (нормальное, инт) перечисление выглядит так:
.class public auto ansi serializable sealed BarFlag extends System.Enum
{
.custom instance void System.FlagsAttribute::.ctor()
.custom instance void ComVisibleAttribute::.ctor(bool) = { bool(true) }
.field public static literal valuetype BarFlag AllFlags = int32(0x3fff)
.field public static literal valuetype BarFlag Foo1 = int32(1)
.field public static literal valuetype BarFlag Foo2 = int32(0x2000)
// and so on for all flags or enum values
.field public specialname rtspecialname int32 value__
}
Что должно привлечь ваше внимание здесь заключается в том, что значение __
хранится отдельно от значения enum. В случае перечисления с Foo
выше, типа значение __
это типа INT16. Это означает, что вы можете хранить все, что вы хотите в перечислимый, покуда типы соответствия.
В этот момент я'd, как, чтобы указать, что система.Перечисление-это тип значения, который в основном означает, что BarFlag будет занимать 4 байта в памяти и с foo
будет занимать 2 -- например, размер базового типа (он'ов на самом деле сложнее, но все же...).
Ответ
Поэтому, если у вас есть целочисленное значение, которое вы хотите отобразить на перечисление, выполнения только 2 вещи: скопировать 4 байта и имя это что-то другое (имя перечисления). Копирование является неявным, поскольку данные хранятся как тип значения - это означает, что если вы использовать неуправляемый код, вы можете просто развязка перечислений и целых чисел без копирования данных.
Чтобы сделать его безопасным, я думаю, что это's не рекомендуется знать, что базовые типы являются одинаковыми или неявно преобразуемым и обеспечить перечисление значений (они не'т включен по умолчанию!).
Чтобы увидеть, как это работает, попробуйте следующий код:
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();
}
Отметим, что кастинг в " Е2 " тоже работает! От компилятора точки зрения выше в этом есть смысл: значение __
поле просто заполняется либо 5 или 6 и при этом консоль.Строку вызывает метод toString(), название
Е1` будет решен в то время как имя " Е2 " не.
Если это's не то, что вы хотели, используйте перечисление.Метод 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 one = 1;
MyEnum e = (MyEnum)one;
Я использую этот кусок кода для приведения 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;
}
}
Для числовых значений, это является более безопасным, так как он возвращает объект, неважно, что:
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;
}
}
Если вы'вновь готовы к 4.0 .Сетка Основы, там's новый перечисление.Метод tryparse() функция'ы очень полезно и хорошо играет с атрибут [flags]. См. Перечисление.Метод tryparse
Если у вас есть целое число, которое выступает в качестве битовой маской и может представлять одно или несколько значений в [флаги] перечисление, вы можете использовать этот код для разбора отдельных значений флага в список:
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);
}
}
Заметим, что это предполагает, что базовый тип перечисление
является 32-разрядное целое число. Если бы это был другой числовой тип, вы'd должны изменить жестко 32, чтобы отразить бит этого типа (или программно извлечь его с помощью перечисления.GetUnderlyingType()`)
Это флаговым курсе безопасный метод Convert:
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;
}
Для преобразования строки в int в enum или ПЕРЕЧИСЛИМОЙ константы мы должны использовать перечислимый.Функция разбора. Вот видео на YouTube [
которая на самом деле продемонстрировать's с строку и то же самое относится и к инт.Код, как показано ниже, где"красным " и; есть строки и "mycolors и" это цвет перечисление цветом константы.
MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");
Немного уходим от изначального вопроса, но я нашла ответ на стек&ампер;усилитель; nbsp;переливом вопрос получить 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 с помощью дженериков, как в Tawani'утилиты S-класса выше. Я использую его для преобразования командной строке переменные выключатель, который может быть неполной. Поскольку перечисление не может быть 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;
}
}
}
}
}
Для справки: вопрос был про целых, который никто не упомянул также явно преобразовать в enum.Метод tryparse()
Следующие несколько лучше метода расширения
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().
Здесь's мой класс 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>();
Разные способы бросания от перечисление
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);
}
}
Я Дон'т не знаю, где мне взять часть этого расширения перечисление, но это из 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;