¿Cómo convierto int a enum en C#?

Resuelto lomaxx asked hace 16 años • 32 respuestas

¿Cómo lanzo un inta un enumen C#?

lomaxx avatar Aug 27 '08 10:08 lomaxx
Aceptado

De un int:

YourEnum foo = (YourEnum)yourInt;

De una cadena:

YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString);

// The foo.ToString().Contains(",") check is necessary for 
// enumerations marked with a [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 número:

YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum), yourInt);
FlySwat avatar Aug 27 '2008 03:08 FlySwat

Simplemente tíralo:

MyEnum e = (MyEnum)3;

Compruebe si está dentro del alcance usando Enum.IsDefined:

if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }
Matt Hamilton avatar Aug 27 '2008 04:08 Matt Hamilton

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>();
Abdul Munim avatar Nov 11 '2011 13:11 Abdul Munim

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, puedes elegir el tipo integral al que se asigna tu enumeración:

public enum Foo : short

En este caso, la enumeración se asigna al shorttipo de datos, lo que significa que se almacenará en la memoria como un short y se comportará como un short cuando lo transmitas y uses.

Si lo miras desde el 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 se value__almacena por separado de los valores de enumeración. En el caso de la enumeración Fooanterior, el tipo de value__es int16. Básicamente, esto 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.Enumes un tipo de valor, lo que básicamente significa que BarFlagocupará 4 bytes en la memoria y Fooocupará 2, por ejemplo, el tamaño del tipo subyacente (en realidad es más complicado que eso, pero ey...).

La respuesta

Entonces, si tiene un número entero que desea asignar a una enumeración, el tiempo de ejecución solo tiene que hacer 2 cosas: copiar los 4 bytes y nombrarlo de otra manera (el nombre de la enumeración). La copia es implícita porque los datos se almacenan como tipo de valor; esto básicamente significa que si usa código no administrado, puede simplemente 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 de enumeración existan (¡no están marcados 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 enviar a e2también funciona! Desde la perspectiva del compilador anterior, esto tiene sentido: el value__campo simplemente se completa con 5 o 6 y cuando Console.WriteLinese llama ToString(), el nombre de e1se resuelve mientras que el nombre de e2no.

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

También tenga en cuenta que soy explícito sobre el tipo subyacente de la enumeración, aunque el compilador realmente lo verifica. Estoy haciendo esto para asegurarme de no encontrarme con sorpresas en el futuro. Para ver estas sorpresas en acción, puedes usar el siguiente código (de hecho, 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();
}
atlaste avatar Apr 03 '2014 07:04 atlaste

Tomemos el siguiente ejemplo:

int one = 1;
MyEnum e = (MyEnum)one;
abigblackman avatar Aug 27 '2008 04:08 abigblackman

Estoy usando este fragmento de código para transmitir inta mi enum:

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

Me parece la mejor solución.

MSkuta avatar Oct 21 '2011 10:10 MSkuta