¿Cómo lanzar int a enum?

Respuestas:

3794

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

De un int:

YourEnum foo = (YourEnum)yourInt;

Actualizar:

Del número también puedes

YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);
FlySwat
fuente
31
@FlySwat, ¿qué YourEnumpasa si es dinámico y solo se sabrá en tiempo de ejecución, y lo que quiero es convertir Enum?
Shimmy Weitzhandler
226
Tenga en cuenta que Enum.Parse NO funcionará si su código está ofuscado. En el tiempo de ejecución después de la ofuscación, la cadena se compara con los nombres de las enumeraciones, y en este punto los nombres de las enumeraciones no son lo que esperaría que fueran. Su análisis fallará donde tuvieron éxito antes como resultado.
jropella
158
CUIDADO Si usa la sintaxis "de una cadena" anterior y pasa una cadena no válida que es un número (por ejemplo, "2342342", suponiendo que no sea un valor de su enumeración), ¡en realidad lo permitirá sin arrojar un error! Su enumeración tendrá ese valor (2342342) aunque no sea una opción válida en la enumeración misma.
JoeCool
132
Creo que esta respuesta está un poco anticuada ahora. Para la cadena, realmente debería usar var result = Enum.TryParse(yourString, out yourEnum)hoy en día (y verificar el resultado para determinar si la conversión falló).
Justin T Conroy
20
También es posible que no Enum.ParsetrueYourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString, true);
distinga
900

Solo échalo:

MyEnum e = (MyEnum)3;

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

if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }
Matt Hamilton
fuente
218
Tenga en cuenta que no puede usar Enum.IsDefined si usa el atributo Flags y el valor es una combinación de banderas, por ejemplo: Keys.L | Keys.Control
ingrese el
15
Al respecto Enum.IsDefined, tenga en cuenta que puede ser peligroso: msdn.microsoft.com/en-us/library/ms229025(VS.90).aspx
adrian
3
Prefiero esta definición: "Devuelve una indicación de si existe una constante con un valor específico en una enumeración especificada" de MSDN
Pap
3
... Porque su definición puede ser engañosa, porque está diciendo: "... verifique si está dentro del rango ..." lo que implica dentro de un rango de números con límites iniciales y finales ...
Pap
3
@ mac9416 He tratado de dar un ejemplo sucinto en gist.github.com/alowdon/f7354cda97bac70b44e1c04bc0991bcc - básicamente al usar IsDefinedpara verificar los valores de entrada, te vuelves vulnerable a las personas que agregan nuevos valores de enumeración más tarde que pasarían un IsDefinedcheque (ya que el nuevo el valor existe en el nuevo código), pero que podría no funcionar con el código original que escribió. Por lo tanto, es más seguro especificar explícitamente los valores de enumeración que su código puede manejar.
adrian
238

Alternativamente, use un método de extensión en lugar de una 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
fuente
77
Para procesar la entrada del usuario, probablemente sea una buena idea llamar a la sobrecarga de Enum.Parse, que le permite especificar que la comparación NO distingue entre mayúsculas y minúsculas (es decir, un usuario que escribe "rojo" (minúscula) bloqueará el código anterior sin este cambio) .)
BrainSlugs83
99
Práctico, pero la pregunta se refiere específicamente a ints.
BJury
2
esto también funciona si la cadena es un número entero, por ejemplo, "2"
TruthOf42
2
Esto arrojará una excepción si enumString es nulo (tuvo un problema similar ayer). Considere usar TryParse en lugar de Parse. TryParse también verificará si T es un tipo de enumeración
Justin
Este tipo de método de extensión System.Stringparece contaminación del espacio de nombres
Sr. Anderson
160

Creo que para obtener una respuesta completa, las personas deben 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, en realidad puede elegir el tipo integral al que se asigna su 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 corto y se comportará como un corto cuando lo emite y usa.

Si lo mira 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 value__se 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 puede almacenar lo que quiera 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 Oye...).

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 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 enteros sin copiar datos.

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

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 casting e2también funciona. Desde la perspectiva del compilador anterior, esto tiene sentido: el value__campo simplemente se llena con 5 o 6 y cuando se Console.WriteLinellama ToString(), el nombre de e1se resuelve mientras que el nombre de e2no lo es.

Si eso no es lo que pretendía, use Enum.IsDefined(typeof(MyEnum), 6)para verificar si el valor que está asignando 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 verifica esto. Estoy haciendo esto para asegurarme de no encontrarme con sorpresas en el futuro. 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();
}
atlaste
fuente
77
Me doy cuenta de que esta es una publicación antigua, pero ¿cómo obtienes este nivel de conocimiento en C #? ¿Es esto de leer a través de la especificación C #?
Rolan
20
@Rolan A veces deseo que más gente pregunte eso. :-) Para ser honesto, realmente no lo sé; Trato de entender cómo funcionan las cosas y obtener información donde pueda obtenerla. Leí el estándar C #, pero también descompilo regularmente el código con Reflector (incluso miro mucho el código del ensamblador x86) y realizo toneladas de pequeños experimentos. Además, conocer otros idiomas ayuda en este caso; He estado haciendo CS durante unos 30 años, y en algún momento ciertas cosas se vuelven 'lógicas' - f.ex. una enumeración debería ser tipos integrales, porque de lo contrario la interoperabilidad se romperá (o su rendimiento se irá por el desagüe).
atlaste
99
Creo que la clave para hacer ingeniería de software correctamente es saber cómo funcionan las cosas. Para mí eso significa que si escribes un código, sabes cómo se traduce aproximadamente a f.ex. operaciones del procesador y recuperación / escritura de memoria. Si pregunta cómo llegar a ese nivel, le sugiero que cree una tonelada de casos de prueba pequeños, haciéndolos más difíciles a medida que avanza, intente predecir el resultado cada vez y pruébelos después (incl. Descompilación, etc.). Después de descubrir todos los detalles y todas las características, puede verificar si acertó en el estándar (aburrido). Al menos, ese sería mi enfoque.
atlaste
1
Fantástica respuesta, gracias! En su último ejemplo de código, arroja una excepción en tiempo de ejecución porque o es un objeto. Puede convertir una variable int en un valor corto siempre que se encuentre dentro del rango corto.
gravidThoughts
@gravidThoughts Gracias. En realidad es una operación de desempaquetado, por lo que no realizará conversiones implícitas como las que usted describe. El envío a veces es confuso en C # si no conoce los detalles ... De todos modos, porque int! = short, Arrojará (falla el desempaquetado). Si lo hace object o = (short)5;, funcionará, porque entonces los tipos coincidirán. No se trata del rango, se trata realmente del tipo.
Atlas
121

Tome el siguiente ejemplo:

int one = 1;
MyEnum e = (MyEnum)one;
abigblackman
fuente
64

Estoy usando este código para transmitir 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.

MSkuta
fuente
1
Esto es bueno. Me sorprendió que no haya una excepción al emitir un valor no válido a una enumeración respaldada por int.
orion elenzil
Esto en realidad no es tan diferente a la respuesta mejor calificada. Esa respuesta también discute el uso de Enum.IsDefined después de haber convertido la cadena al tipo Enum. Entonces, incluso si la cadena se fundió sin error, Enum.IsDefined todavía la atrapará
Don Cheadle,
53

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;
    }
}
Tawani
fuente
47

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;
    }
}
Sébastien Duval
fuente
No funciona para la enumeración de banderas
Seyed Morteza Mousavi
44

Si está listo para 4.0 .NET Framework, hay una nueva función Enum. TryParse () que es muy útil y funciona bien con el atributo [Flags]. Ver método Enum. TryParse (String, TEnum%)

Ryan Russon
fuente
21
Eso es útil cuando se convierte desde una cadena. Pero no cuando se convierte de un int.
CodesInChaos
35

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 [Banderas], puede usar este código para analizar los valores de las banderas individuales en una lista:

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

Tenga en cuenta que esto supone que el tipo subyacente del enumes un entero de 32 bits con signo. Si fuera un tipo numérico diferente, tendría que cambiar el 32 codificado para reflejar los bits en ese tipo (o derivarlo programáticamente usando Enum.GetUnderlyingType())

Evan M
fuente
1
¿Este ciclo nunca termina? flagIterator = 0x00000001, flagIterator = 0x00000002, flagIterator = 0x00000004, ..., flagIterator = 0x40000000, flagIterator = 0x80000000, flagIterator = 0x00000000. En otras palabras, el valor siempre será inferior a 0x80000000 porque se desbordará a cero después del caso donde el bit D31 = 1. Luego, permanecerá 0 para siempre porque al cambiar a la izquierda el valor 0 da 0
Christian Gingras
Gran captura @christiangingras, gracias! He modificado la respuesta para tener en cuenta eso, y debería tenerlo en cuenta cuando se establece el bit más alto (es decir, 0x80000000 / Int32.MinValue)
Evan M
27

A veces tienes un objeto para el MyEnumtipo. Me gusta

var MyEnumType = typeof(MyEnumType);

Entonces:

Enum.ToObject(typeof(MyEnum), 3)
LD
fuente
26

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

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;
}
Daniel Fisher lennybacon
fuente
3
¡Esto ahora se puede mejorar con C # 7.3 restringiendo en Enumlugar de struct, lo que significa que no tenemos que depender de la verificación del tiempo de ejecución!
Scott
20

ingrese la descripción de la imagen aquí

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 realmente demuestra con cadena y lo mismo 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");
Shivprasad Koirala
fuente
20

Me alejé un poco de la pregunta original, pero encontré una respuesta a la pregunta de desbordamiento de pila. Obtener el valor int de enum es útil. Cree una clase estática con public const intpropiedades, que le permita recopilar fácilmente un montón de intconstantes relacionadas , y luego no tener que convertirlas intal usarlas.

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 enum, pero para almacenar un montón de constantes de identificación de la base de datos, parece una solución bastante ordenada.

Ted
fuente
55
los enumeradores reemplazaron el uso de constantes enteras como esta, ya que proporcionan más seguridad de tipo
Paul Richards
1
Paul, este es un método para recopilar constantes int relacionadas (por ejemplo, constantes de id de base de datos) para que puedan usarse directamente sin tener que convertirlas en int cada vez que se usan. Su tipo es entero, no por ejemplo, DatabaseIdsEnum.
Ted
1
He encontrado al menos una situación en la que la seguridad de tipo enum puede omitirse involuntariamente.
Thierry
Pero las enumeraciones también aseguran que todos los valores sean únicos, algo de lo que también carece este enfoque
derHugo
15

Esto analiza enteros o cadenas a una enumeración de destino con 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 comandos 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;
                }
            }
        }
    }
}

FYI: La pregunta era sobre números enteros, que nadie mencionó también se convertirá explícitamente en Enum. TryParse ()

CZahrobsky
fuente
13

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

enum Importance
{}

Importance importance;

if (Enum.TryParse(value, out importance))
{
}
Will Yu
fuente
44
La pregunta se refiere específicamente a los enteros.
BJury
44
Will Yu, por favor, edite su respuesta para que todos sepan Enum. TryParse funcionará en una cadena del valor o nombre de la enumeración (no pude resistir)
JeremyWeir
1
Jeremy, Weir trabajando en eso (tampoco pudo resistirse).
huysentruitw
11

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;
        }
Kamran Shahid
fuente
10

En mi caso, necesitaba devolver la enumeración de un servicio WCF. También necesitaba un nombre descriptivo, no solo el enum.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 de la enumeración.

    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>();
LawMan
fuente
9

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

Debería incorporar algún tipo de relajación coincidente para ser más robusto.

public static T ToEnum<T>(dynamic value)
{
    if (value == null)
    {
        // default value of an enum is the object that corresponds to
        // the default value of its underlying type
        // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/default-values-table
        value = Activator.CreateInstance(Enum.GetUnderlyingType(typeof(T)));
    }
    else if (value is string name)
    {
        return (T)Enum.Parse(typeof(T), name);
    }

    return (T)Enum.ToObject(typeof(T),
             Convert.ChangeType(value, Enum.GetUnderlyingType(typeof(T))));
}

Caso de prueba

[Flags]
public enum A : uint
{
    None  = 0, 
    X     = 1 < 0,
    Y     = 1 < 1
}

static void Main(string[] args)
{
    var value = EnumHelper.ToEnum<A>(7m);
    var x = value.HasFlag(A.X); // true
    var y = value.HasFlag(A.Y); // true

    var value2 = EnumHelper.ToEnum<A>("X");

    var value3 = EnumHelper.ToEnum<A>(null);

    Console.ReadKey();
}

fuente
Esta es una buena respuesta. ¡Es una pena que esté tan abajo de la página en este momento!
MikeBeaton
8

Diferentes formas de emitir 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);


 }
}
usuario de gmail
fuente
8

Puede ayudarlo a convertir cualquier dato de entrada a la enumeración deseada por el usuario . Supongamos que tiene una enumeración como la siguiente, que por defecto es int . Agregue un valor predeterminado al principio de su enumeración. Que se utiliza en el método de ayuda cuando no se encuentra una 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 por defecto int Si define enum como este, que es el tipo de byte .

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

Debe cambiar el análisis en el método auxiliar de

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

a

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

Compruebo 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

reza.cse08
fuente
8

Aquí es un método de extensión que se proyecta Int32a Enum.

Honra las banderas bit a bit incluso cuando el valor es más alto que el máximo posible. Por ejemplo, si tiene una enumeración con las posibilidades 1 , 2 y 4 , pero el int es 9 , entiende que es 1 en ausencia de un 8 . Esto le permite realizar actualizaciones de datos antes de las actualizaciones de código.

   public static TEnum ToEnum<TEnum>(this int val) where TEnum : struct, IComparable, IFormattable, IConvertible
    {
        if (!typeof(TEnum).IsEnum)
        {
            return default(TEnum);
        }

        if (Enum.IsDefined(typeof(TEnum), val))
        {//if a straightforward single value, return that
            return (TEnum)Enum.ToObject(typeof(TEnum), val);
        }

        var candidates = Enum
            .GetValues(typeof(TEnum))
            .Cast<int>()
            .ToList();

        var isBitwise = candidates
            .Select((n, i) => {
                if (i < 2) return n == 0 || n == 1;
                return n / 2 == candidates[i - 1];
            })
            .All(y => y);

        var maxPossible = candidates.Sum();

        if (
            Enum.TryParse(val.ToString(), out TEnum asEnum)
            && (val <= maxPossible || !isBitwise)
        ){//if it can be parsed as a bitwise enum with multiple flags,
          //or is not bitwise, return the result of TryParse
            return asEnum;
        }

        //If the value is higher than all possible combinations,
        //remove the high imaginary values not accounted for in the enum
        var excess = Enumerable
            .Range(0, 32)
            .Select(n => (int)Math.Pow(2, n))
            .Where(n => n <= val && n > 0 && !candidates.Contains(n))
            .Sum();

        return Enum.TryParse((val - excess).ToString(), out asEnum) ? asEnum : default(TEnum);
    }
Chad Hedgcock
fuente
6

La forma fácil y clara de enviar un int a enum en C #:

 public class Program
    {
        public enum Color : int
        {
            Blue = 0,
            Black = 1,
            Green = 2,
            Gray = 3,
            Yellow =4
        }

        public static void Main(string[] args)
        {
            //from string
            Console.WriteLine((Color) Enum.Parse(typeof(Color), "Green"));

            //from int
            Console.WriteLine((Color)2);

            //From number you can also
            Console.WriteLine((Color)Enum.ToObject(typeof(Color) ,2));
        }
    }
Mohammad Aziz Nabizada
fuente
6

Simplemente usa la conversión explícita Cast int to enum o enum to int

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine((int)Number.three); //Output=3

        Console.WriteLine((Number)3);// Outout three
        Console.Read();
    }

    public enum Number
    {
        Zero = 0,
        One = 1,
        Two = 2,
        three = 3
    }
}
Shivam Mishra
fuente
4
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace SamplePrograme
{
    public class Program
    {
        public enum Suit : int
        {
            Spades = 0,
            Hearts = 1,
            Clubs = 2,
            Diamonds = 3
        }

        public static void Main(string[] args)
        {
            //from string
            Console.WriteLine((Suit) Enum.Parse(typeof(Suit), "Clubs"));

            //from int
            Console.WriteLine((Suit)1);

            //From number you can also
            Console.WriteLine((Suit)Enum.ToObject(typeof(Suit) ,1));
        }
    }
}
Aswal
fuente
3

Simplemente haz lo siguiente:

int intToCast = 1;
TargetEnum f = (TargetEnum) intToCast ;

Para asegurarse de que solo emite los valores correctos y de lo contrario puede lanzar una excepción:

int intToCast = 1;
if (Enum.IsDefined(typeof(TargetEnum), intToCast ))
{
    TargetEnum target = (TargetEnum)intToCast ;
}
else
{
   // Throw your exception.
}

Tenga en cuenta que usar IsDefined es costoso e incluso más que solo transmitir, por lo que depende de su implementación decidir si lo usa o no.

Mselmi Ali
fuente
3

Puedes usar el método de extensión.

public static class Extensions
{

    public static T ToEnum<T>(this string data) where T : struct
    {
        if (!Enum.TryParse(data, true, out T enumVariable))
        {
            if (Enum.IsDefined(typeof(T), enumVariable))
            {
                return enumVariable;
            }
        }

        return default;
    }

    public static T ToEnum<T>(this int data) where T : struct
    {
        return (T)Enum.ToObject(typeof(T), data);
    }
}

utilizar como código de abajo

enumeración:

public enum DaysOfWeeks
{
    Monday = 1,
    Tuesday = 2,
    Wednesday = 3,
    Thursday = 4,
    Friday = 5,
    Saturday = 6,
    Sunday = 7,
}

Uso:

 string Monday = "Mon";
 int Wednesday = 3;
 var Mon = Monday.ToEnum<DaysOfWeeks>();
 var Wed = Wednesday.ToEnum<DaysOfWeeks>();
Reza Jenabi
fuente