c# español get - Reparto int enum en C #





10 Answers

Sólo tienes que lanzarlo:

MyEnum e = (MyEnum)3;

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

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

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




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

public enum Foo : short

En este caso, la enumeración se asigna al tipo de datos short , lo que significa que se almacenará en la memoria como un breve y se comportará de forma breve cuando se emita y se 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 de enumeración. En el caso de la enumeración Foo anterior, 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.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 entero que desea asignar a una enumeración, el tiempo de ejecución solo tiene que hacer 2 cosas: copie los 4 bytes y asígnele el nombre de otra enumeración (el nombre de la enumeración). La copia es implícita porque los datos se almacenan como tipo de valor; básicamente, esto significa que si usa un código no administrado, puede simplemente intercambiar enums y enteros sin copiar datos.

Para hacerlo 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 se verifican 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 el casting 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 lo es.

Si eso no es lo que pretendía, use Enum.IsDefined(typeof(MyEnum), 6) para verificar si el valor que está asignando se asigna a 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. Estoy haciendo esto para asegurarme de no encontrar ninguna sorpresa en el camino. 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();
}



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




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



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



Este es un método de conversión segura para la enumeración de marcas:

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



Ligeramente alejándome de la pregunta original, pero encontré una respuesta a la pregunta de desbordamiento de pila Obtener valor int de enum útil. Cree una clase estática con propiedades public const int , que le permitan reunir fácilmente un grupo de constantes int relacionadas, y luego no tener que convertirlas en int cuando las utilice.

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




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

enum Importance
{}

Importance importance;

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



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

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



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



Related