type from español enum convert clase cast c# enums casting

c# - español - get enum from int java



Reparto int enum en C# (21)

¿Cómo se puede convertir un int a una enum en C #?


A continuación se muestra una buena clase de utilidad para 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; } }


A veces tienes un objeto para el tipo MyEnum . Me gusta

var MyEnumType = typeof(MyEnumType);

Entonces:

Enum.ToObject(typeof(MyEnum), 3)


Alternativamente, use un método de extensión en lugar de una sola línea:

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

Uso:

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

O

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


Creo que para obtener una respuesta completa, la gente debe saber cómo funcionan las enumeraciones internamente en .NET.

Como funcionan las cosas

Una enumeración en .NET es una estructura que asigna un conjunto de valores (campos) a un tipo básico (el valor predeterminado es int ). Sin embargo, puede elegir el tipo integral que su enumeración asigna para:

public enum Foo : short

En este caso, la enumeración se asigna al tipo de datos short , lo que significa que se almacenará en la memoria como un breve y se comportará de forma breve cuando se emita y se use.

Si lo miras desde un punto de vista de IL, una enumeración (normal, int) se ve así:

.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__ }

Lo que debería llamar su atención aquí es que el value__ se almacena por separado de los valores de enumeración. En el caso de la enumeración Foo anterior, el tipo de value__ es int16. Básicamente, esto significa que puede almacenar lo que quiera en una enumeración, siempre que los tipos coincidan .

En este punto, me gustaría señalar que System.Enum es un tipo de valor, lo que básicamente significa que BarFlag ocupará 4 bytes en la memoria y Foo ocupará 2, por ejemplo, el tamaño del tipo subyacente (en realidad es más Más complicado que eso, pero oye ...).

La respuesta

Por lo tanto, si tiene un entero que desea asignar a una enumeración, el tiempo de ejecución solo tiene que hacer 2 cosas: copie los 4 bytes y asígnele el nombre de otra enumeración (el nombre de la enumeración). La copia es implícita porque los datos se almacenan como tipo de valor; básicamente, esto significa que si usa un código no administrado, puede simplemente intercambiar enums y enteros sin copiar datos.

Para hacerlo seguro, creo que es una buena práctica saber que los tipos subyacentes son los mismos o implícitamente convertibles y garantizar que los valores de enumeración existan (¡no se verifican de forma predeterminada!).

Para ver cómo funciona esto, pruebe el siguiente código:

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

Tenga en cuenta que el casting a e2 también funciona! Desde la perspectiva del compilador anterior, esto tiene sentido: el campo value__ simplemente se rellena con 5 o 6 y cuando Console.WriteLine llama a ToString() , el nombre de e1 se resuelve mientras que el nombre de e2 no lo es.

Si eso no es lo que pretendía, use Enum.IsDefined(typeof(MyEnum), 6) para verificar si el valor que está asignando se asigna a una enumeración definida.

También tenga en cuenta que soy explícito sobre el tipo subyacente de la enumeración, a pesar de que el compilador realmente comprueba esto. Estoy haciendo esto para asegurarme de no encontrar ninguna sorpresa en el camino. Para ver estas sorpresas en acción, puede usar el siguiente código (en realidad, he visto que esto sucede mucho en el código de la base de datos):

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


De una cuerda:

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

De un int:

YourEnum foo = (YourEnum)yourInt;

Actualizar:

Del número también puedes

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


Desde una cadena: (Enum.Parse está desactualizado, use Enum.TryParse)

enum Importance {} Importance importance; if (Enum.TryParse(value, out importance)) { }


Diferentes formas de lanzar desde y hacia 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); } }


En mi caso, tuve que devolver la enumeración de un servicio WCF. También necesitaba un nombre descriptivo, no solo la enumeración.ToString ().

Aquí está mi clase 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; } }

Aquí está el método de Extensión que obtiene la Descripción del 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(); } }

Implementación:

return EnumMember.ConvertToList<YourType>();


Este es un método de conversión segura para la enumeración de marcas:

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


Esto analiza enteros o cadenas a una enumeración de destino con una coincidencia parcial en dot.NET 4.0 usando genéricos como en la clase de utilidad de Tawani anterior. Lo estoy usando para convertir variables de cambio de línea de comando que pueden estar incompletas. Como una enumeración no puede ser nula, lógicamente debe proporcionar un valor predeterminado. Se puede llamar así:

var result = EnumParser<MyEnum>.Parse(valueToParse, MyEnum.FirstValue);

Aquí está el código:

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

Para su información: La pregunta fue sobre los enteros, que nadie mencionó también se convertirá explícitamente en Enum.TryParse ()


Estoy usando este código para lanzar int a mi enumeración:

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

Me parece la mejor solución.


Ligeramente alejándome de la pregunta original, pero encontré una respuesta a la pregunta de desbordamiento de pila Obtener valor int de enum útil. Cree una clase estática con propiedades public const int , que le permitan reunir fácilmente un grupo de constantes int relacionadas, y luego no tener que convertirlas en int cuando las utilice.

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

Obviamente, se perderá parte de la funcionalidad de tipo de enumeración, pero para almacenar un montón de constantes de identificación de base de datos, parece una solución bastante ordenada.


Lo siguiente es un método de extensión ligeramente mejor

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


Para los valores numéricos, esto es más seguro ya que devolverá un objeto sin importar qué:

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


Puede ayudarlo a convertir cualquier dato de entrada a la enumeración deseada por el usuario. Supongamos que tiene una enumeración como la de abajo, que por defecto es int . Agregue un valor predeterminado al principio de su enumeración. Lo que se usa en los ayudantes de mano cuando no se encuentra ninguna coincidencia con el valor de entrada.

public enum FriendType { Default, Audio, Video, Image } public static class EnumHelper<T> { public static T ConvertToEnum(dynamic value) { var result = default(T); var tempType = 0; //see Note below if (value != null && int.TryParse(value.ToString(), out tempType) && Enum.IsDefined(typeof(T), tempType)) { result = (T)Enum.ToObject(typeof(T), tempType); } return result; } }

NB: aquí trato de analizar el valor en int, porque enum es int por defecto si define enum como es el tipo de byte .

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

Es necesario cambiar el análisis en el método de ayuda de

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

a

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

Reviso mi método para las siguientes entradas

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

Lo siento por mi ingles


Sólo tienes que lanzarlo:

MyEnum e = (MyEnum)3;

Puede verificar si está dentro del rango usando Enum.IsDefined :

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



Si tiene un número entero que actúa como una máscara de bits y podría representar uno o más valores en una enumeración de [Banderas], puede usar este código para analizar los valores de las banderas individuales en una lista:

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


Tomemos el siguiente ejemplo:

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


Ya no sé de dónde saco la parte de esta extensión de enumeración, pero es de . ¡Lo siento por esto! Pero tomé éste y lo modifiqué para enums con Flags. Para enums con Flags hice esto:

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

Ejemplo:

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


Para convertir una cadena a ENUM o int a la constante ENUM necesitamos usar la función Enum.Parse. Aquí hay un video de YouTube https://www.youtube.com/watch?v=4nhx4VwdRDk que en realidad demuestra con una cadena y lo mismo se aplica para int.

El código va como se muestra a continuación, donde "rojo" es la cadena y "MyColors" es el color ENUM que tiene las constantes de color.

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