type - get enum string value from int c#




Reparto int enum en C# (14)

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

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


A veces tienes un objeto para el tipo MyEnum . Me gusta

var MyEnumType = typeof(MyEnumType);

Entonces:

Enum.ToObject(typeof(MyEnum), 3)

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

De una cuerda:

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

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


 }
}

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

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

Para su información: La pregunta fue sobre los enteros, que nadie mencionó también se convertirá explícitamente en Enum.TryParse ()


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.


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

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

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


Tomemos el siguiente ejemplo:

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

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;




casting