[c#] Emitir int a enum en C #



Answers

Solo echalo:

MyEnum e = (MyEnum)3;

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

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

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




Para convertir una cadena a ENUM o int a ENUM constante, necesitamos usar la función Enum.Parse. Aquí hay un video de youtube https://www.youtube.com/watch?v=4nhx4VwdRDk que en realidad se muestra con 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");



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 [Flags], puede usar este código para analizar los valores de indicador 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);
    }
}



De una cadena: (Enum.Parse está fuera de fecha, use Enum.TryParse)

enum Importance
{}

Importance importance;

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






Creo que para obtener una respuesta completa, la gente tiene que saber cómo funcionan las enumeraciones internas 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 al que se asigna su enumeración:

public enum Foo : short

En este caso, la enumeración se correlaciona con el tipo de datos short , lo que significa que se almacenará en la memoria de forma breve y se comportará como un corto cuando lo proyecte y lo 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 enum. En el caso del enum Foo anterior, el tipo de value__ es int16. Esto básicamente significa que puedes almacenar lo que quieras 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 número entero que desea asignar a una enumeración, el tiempo de ejecución solo tiene que hacer dos cosas: copiar los 4 bytes y nombrarlo de otra forma (el nombre de la enumeración). La copia está implícita porque los datos se almacenan como tipo de valor; esto básicamente significa que si usa código no administrado, simplemente puede intercambiar enumeraciones y números enteros sin copiar datos.

Para que sea 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 enum existan (¡no están marcados por defecto!).

Para ver cómo funciona esto, prueba 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 la conversión 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 está.

Si eso no es lo que pretendía, use Enum.IsDefined(typeof(MyEnum), 6) para verificar si el valor que está proyectando se correlaciona con 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. Hago esto para asegurarme de no encontrar sorpresas en el futuro. Para ver estas sorpresas en acción, puedes 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();
}



Este es un método seguro de conversión de enumeración de banderas:

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



Estoy usando este fragmento de código para convertir int en mi enumeración:

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

Encuentro que es la mejor solución.




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



Ya no sé de dónde saco la parte de esta extensión enum, pero es de . ¡Lo siento por esto! Pero tomé este y lo modifiqué para enumeraciones con Flags. Para enumeraciones con Banderas, 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;



Related