Pregunta

¿Cómo puede un int ser echado a un enum en C#?

¿Fue útil?

Solución

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

A partir de un entero:

YourEnum foo = (YourEnum)yourInt;

Actualización:

El número también puede

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

Otros consejos

Sólo un cast:

MyEnum e = (MyEnum)3;

Usted puede comprobar si está en el rango de usar Enum.IsDefined:

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

Como alternativa, utilice 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 conseguir una respuesta completa, la gente tiene que saber cómo enumeraciones trabajar internamente en .NET.

How stuff works

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, usted puede elegir el tipo integral que su enumeración mapas para:

public enum Foo : short

En este caso, la enumeración se asigna a la short tipo de datos, lo que significa que se almacena en la memoria como un corto y se comporta como un corto cuando lanzas y utilizarla.

Si usted lo mira desde un IL punto de vista, un (normal, int) enum se parece a esto:

.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 debe llamar su atención aquí es que la value__ se almacena por separado de los valores de enumeración.En el caso de la enumeración Foo anteriormente, el tipo de value__ es int16.Básicamente, esto significa que usted puede almacenar todo lo que usted desea en una enumeración, mientras coincidan con los tipos.

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

La respuesta

Por lo tanto, si usted tiene un número entero que desea asignar a un enum, el tiempo de ejecución sólo tiene que hacer 2 cosas:copiar los 4 bytes y el nombre de algo más (el nombre de la enumeración).La copia es implícita porque los datos se almacena como valor de tipo básicamente, esto significa que si usted usa el código no administrado, usted puede simplemente intercambio de las enumeraciones y enteros, sin copiar los datos.

Para que sea segura, creo que es una de las mejores prácticas para sabemos que el subyacente tipos son los mismos o implícitamente convertible y para garantizar la enumeración de los valores de existir (que no se verifican por defecto!).

Para ver cómo funciona, pruebe con 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 el compilador perspectiva por encima de esto tiene sentido:el value__ campo es simplemente rellena con 5 o 6 y cuando Console.WriteLine llamadas ToString(), el nombre de e1 se resuelve, mientras que el nombre de e2 no es.

Si eso no es lo que pretende, uso Enum.IsDefined(typeof(MyEnum), 6) para comprobar si el valor que se va a convertir mapas a un enum.

También tenga en cuenta que estoy explícita sobre el tipo subyacente de la enumeración, aunque el compilador comprueba en realidad esta.Estoy haciendo esto para asegurarse de que no se ejecute en cualquier sorpresas por el camino.Para ver estas sorpresas en la acción, usted puede usar el siguiente código (de hecho, he visto esto sucede mucho en la base de datos de código):

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

Tomemos el siguiente ejemplo:

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

Estoy usando este trozo de 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.

A continuación es una buena clase de utilidad para las Enumeraciones

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

Para valores numéricos, esto es más seguro, ya que va a devolver un objeto no importa 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;
    }
}

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

Si usted tiene un número entero que actúa como una máscara de bits y podría representar uno o más valores en un [Banderas] la enumeración, puede utilizar este código para analizar el individuo los valores del indicador 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 de la enum es un entero de 32 bits con signo.Si se tratara de un diferente tipo numérico, tendrías que cambiar el codificado 32 para reflejar los bits de ese tipo (o a través de programación derivar usando Enum.GetUnderlyingType())

A veces usted tiene un objeto para el MyEnum tipo.Como

var MyEnumType = typeof(MyEnumType);

Entonces:

Enum.ToObject(typeof(MyEnum), 3)

Esta es una enumeración de indicadores consciente de seguros convertir método:

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

enter image description here

Para convertir una cadena a ENUM o int ENUM constante necesitamos utilizar Enum.Función de análisis.Aquí está un vídeo de youtube https://www.youtube.com/watch?v=4nhx4VwdRDk que en realidad demuestran con cadena y lo mismo se aplica para int.

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

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

Ligeramente alejarse de la pregunta original, pero he encontrado una respuesta de Desbordamiento de la Pila pregunta Obtener int valor de enumeración útil.Crear una clase estática con public const int propiedades, permitiendo una fácil reunir un montón de relacionados int constantes, y luego no tienen para echarlos a int cuando el uso de ellos.

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, algunos de los enum tipo de funcionalidad se pierde, pero para almacenar un montón de identificador de base de datos constantes, parece un muy ordenado solución.

Este analiza enteros o cadenas de caracteres a un objetivo enum con parciales de coincidencia en dot.NET 4.0 el uso de medicamentos genéricos como en Tawani la utilidad de la clase anterior.La estoy usando para convertir el modificador de línea de comandos de las variables que pueden estar incompletos.Desde una enumeración no puede ser null, debe lógicamente proporcionar un valor predeterminado.Puede ser llamado como este:

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 acerca de los números enteros, que nadie ha mencionado también convertir explícitamente en la Enumeración.TryParse()

A partir de una cadena:(Enum.Analizar es el de la Fecha, el uso de la Enumeración.TryParse)

enum Importance
{}

Importance importance;

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

Siguiente es ligeramente mejor método de extensión

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

En mi caso, necesitaba volver a la enumeración de un servicio WCF.Yo también necesitaba un nombre descriptivo, no sólo de la enumeración.ToString().

Aquí está mi WCF Clase.

[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 se obtiene de 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();
        }
    }

Aplicación:

return EnumMember.ConvertToList<YourType>();

Diferentes maneras de fundición y a partir de 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);


 }
}

Ya no sé donde puedo conseguir la parte de esta enumeración de extensión, pero es a partir de stackoverflow.Lo siento por esto!Pero tomé esta uno y modificado por las enumeraciones con Banderas.Para las 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;

Puede ayudarle a convertir los datos de entrada del usuario deseado enum.Supongamos que usted tiene un enum como el de abajo, que, por defecto, int.Por favor, añadir un Por defecto valor al principio de su enumeración.Es el que se usa ayudantes de aportarse cuando no hay no se encontró 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;
    }
}

N. B: Aquí trato de analizar el valor en int, porque enum es por defecto int Si se define enum como esta que se byte tipo.

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

Necesita cambiar de análisis en el método de ayudante de

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

a

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

Puedo comprobar mi método para 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 inglés

He aquí un método de extensión que arroja Int32 a Enum.

Honra indicadores bit a bit, incluso cuando el valor es mayor que el máximo posible.Por ejemplo, si usted tiene un enum con posibilidades 1, 2, y 4, pero la int es 9, se entiende que la 1 en ausencia de un 8.Esto le permite realizar actualizaciones de datos por delante 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);
    }

la forma clara y sencilla para la emisión de una int 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));
        }
    }

Sólo tiene que utilizar La conversión explícita de la Cast int enum o enum a 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           
        }
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top