Pregunta Emitir int a enum en C #


¿Cómo puede un int ser lanzado a un enum Cª#?


2565
2017-08-27 03:58


origen


Respuestas:


De una cadena:

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

Desde un int:

YourEnum foo = (YourEnum)yourInt;

Actualizar:

Desde el número también puedes

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

3115
2017-08-27 03:59



Solo echalo:

MyEnum e = (MyEnum)3;

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

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

718
2017-08-27 04:01



Alternativamente, use un método de extensión en lugar de un trazador de líneas:

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

197
2017-11-11 13:27



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 asigna a la short tipo de datos, lo que significa que se almacenará en la memoria como un resumen 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 la value__ se almacena por separado de los valores enum. En el caso de la enumeración Foo arriba, 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 memoria y Foo tomará 2, por ej. el tamaño del tipo subyacente (en realidad es más complicado que eso, pero bueno ...).

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 para asegurar que existan los valores enum (¡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 el lanzamiento a e2 ¡también funciona! Desde la perspectiva del compilador anterior, esto tiene sentido: el value__ campo se llena simplemente con 5 o 6 y cuando Console.WriteLine llamadas ToString(), el nombre de e1 se resuelve mientras el nombre de e2 no es.

Si eso no es lo que pretendías, usa Enum.IsDefined(typeof(MyEnum), 6) para verificar si el valor que estás 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();
}

116
2018-04-03 07:39



Toma el siguiente ejemplo:

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

89
2017-08-27 04:00



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.


54
2017-10-21 10:05



A continuación hay 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;
    }
}

44
2017-09-07 04:42



Si estás listo para el 4.0 .RED Marco, hay un nuevo Enum.TryParse () función que es muy útil y juega bien con el atributo [Flags]. Ver Método Enum.TryParse (String, TEnum%)


37
2017-11-01 14:58



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

37
2018-02-21 15:22