Me gustaría crear un método genérico para la conversión de cualquier Sistema.Enum tipo derivado a su valor entero correspondiente, sin casting y, preferentemente, sin necesidad de analizar una cadena.

Por ejemplo, lo que yo quiero es algo como esto:

//Trivial example, not actually what I'm doing.
class Converter
{
    int ToInteger(System.Enum anEnum)
    {
        (int)anEnum;
    }
}

Pero esto no parece funcionar. Resharper informes que usted no puede emitir expresión de tipo ‘System.Enum’ de tipo ‘int’.

Ahora me he encontrado con esta solución, pero yo prefiero tener algo más eficiente.

class Converter
{
    int ToInteger(System.Enum anEnum)
    {
        return int.Parse(anEnum.ToString("d"));
    }
}

Alguna sugerencia?

  • Creo que es el compilador que se está quejando, no Resharper.
  • No necesariamente. Tengo un método de extensión en el Sistema.Enum, y ocasionalmente Resharper decide quejarse: No se puede convertir instancia argumento de tipo ‘Algunos.Fresco.Tipo.Que.Es.Una.Enum (‘a ‘del Sistema.Enum’ cuando es, sin duda, ES una enumeración. Si puedo compilar y ejecutar el código que funciona bien. Si yo, a continuación, apague VS, sople el Resharper caché, y el fuego de nuevo, todo está bien una vez que su hecho volver a recorrer. Para mí se trata de algún tipo de caché de bodrio. Podría ser lo mismo para él.
  • He tenido ReSharper «quejarse» en esto también. Mismo fix para mí. No sé por qué se pone estos tipos se mezclan, pero definitivamente no es el compilador.
InformationsquelleAutor orj | 2009-05-26

8 Comentarios

  1. 129

    Si no quieren echar,

    Convert.ToInt32()

    podría hacer el truco.

    Directa cast (a través de (int)enumValue) no es posible. Tenga en cuenta que esto también podría ser «peligroso», ya que una enumeración puede basan en diferentes tipos de (int, long, byte…).

    Más formalmente: System.Enum no tiene directa relación de herencia con Int32 (aunque ambos son ValueTypes), por lo que la conversión explícita no puede ser correcta en el sistema de tipo de

    • Converter.ToInteger(MyEnum.MyEnumConstant); le dará ningún error aquí. Por favor, edite esa parte.
    • Gracias, @nawfal, tienes razón. He editado la respuesta (y aprendido algo nuevo 🙂 …)
    • No funciona si el tipo subyacente difiere de int
    • Probado con sbyte de trabajo
    • no trabajo por ejemplo, para long enum.
    • System.Enum es una clase, por lo que es un tipo de referencia. Los valores son, probablemente, en caja.

  2. 38

    Yo tengo que trabajar por la conversión a un objeto y, a continuación, a un int:

    public static class EnumExtensions
    {
        public static int ToInt(this Enum enumValue)
        {
            return (int)((object)enumValue);
        }
    }

    Esta es feo y que probablemente no sea la mejor manera. Voy a seguir jugando con ella, a ver si puedo llegar a algo mejor….

    EDIT: Estaba a punto de publicar que Convertir.ToInt32(enumValue) funciona igual de bien, y se dio cuenta de que MartinStettner me pegaba a él.

    public static class EnumExtensions
    {
        public static int ToInt(this Enum enumValue)
        {
            return Convert.ToInt32(enumValue);
        }
    }

    Prueba:

    int x = DayOfWeek.Friday.ToInt();
    Console.WriteLine(x); //results in 5 which is int value of Friday

    EDIT 2: En los comentarios, alguien dijo que esto sólo funciona en C# 3.0. Acabo de probar esto en VS2005 como este y funcionó:

    public static class Helpers
    {
        public static int ToInt(Enum enumValue)
        {
            return Convert.ToInt32(enumValue);
        }
    }
    
        static void Main(string[] args)
        {
            Console.WriteLine(Helpers.ToInt(DayOfWeek.Friday));
        }
    • Te di +1, pero esta solución es la que vamos a trabajar sólo con C# 3.0 y superior.
    • Creo, esto sólo satisface el compilador. Te las has arreglado para poner a prueba esta en tiempo de ejecución? Yo no podía pasar cualquier valor para esta función…
    • Porque es un método de extensión? O es algo diferente acerca de las enumeraciones en las versiones anteriores de C#?
    • He añadido una prueba para el final de mi post. Lo probé y funcionó para mí.
    • Parece que sólo a trabajar con los métodos de extensión. He probado con un «viejo estilo» de la función (en C# 2.0) y no se las arreglan para encontrar la sintaxis para realmente pasar cualquier valor (que es lo que mi anterior comentario fue acerca de)
    • Si quieres un verdadero reto, tratar de ir en la dirección opuesta, a partir de un parámetro de tipo genérico TEnum a un int. Buena suerte!

  3. 12

    Si usted necesita para convertir cualquier enum para su tipo subyacente (no todas las enumeraciones son respaldados por int), entonces usted puede utilizar:

    return System.Convert.ChangeType(
        enumValue,
        Enum.GetUnderlyingType(enumValue.GetType()));
    • Esta es la única respuesta a prueba de balas.
    • Esto sin duda se debe ser aceptada respuesta.
    • Es esta la causa de boxeo unboxing?
    • sí. Convert.ChangeType acepta object para el primer argumento, y devuelve object.
  4. 10

    ¿Por qué es necesario reinventar la rueda con un método helper? Es perfectamente legal para emitir una enum valor a su tipo subyacente.

    Es escribir menos, y en mi opinión más legible, para usar…

    int x = (int)DayOfWeek.Tuesday;

    …en lugar de algo como…

    int y = Converter.ToInteger(DayOfWeek.Tuesday);
    //or
    int z = DayOfWeek.Tuesday.ToInteger();
    • Quiero convertir CUALQUIER valor de enumeración. Es decir, tengo una variedad de clases que tienen enumeración de los campos que están siendo procesados por el código de una manera genérica. Esta es la razón por la que un simple elenco de int no es apropiado.
    • No estoy realmente seguro de lo que quieres decir. ¿Puede dar un ejemplo que muestra el uso que usted necesita?
    • A veces no se puede lanzar directamente una enumeración, como en el caso de un método genérico. Debido a que los métodos genéricos no puede ser limitada a las enumeraciones, usted tiene limitan a algo así como una estructura, la cual no puede ser fundido en un int. En ese caso, puede utilizar Convertir.ToInt32(enum) para hacerlo.
    • Me gusta la idea de que el método de extensión ToInteger() sigue el mismo formato como ToString(). Creo que es menos legible para la conversión a int en una mano cuando se desea que el valor de int y el uso ToString() cuando necesitamos de la cadena de valor, especialmente cuando el código es lado por lado.
    • Además, el uso de un método de extensión puede añadir consistencia a su base de código. Ya que, como @nawfal señalado, hay varias maneras que usted puede conseguir el int valor de una enumeración, la creación de un método de extensión y la aplicación de su uso significa que cada vez que usted consigue la int valor de una enumeración está utilizando el mismo método
  5. 4

    De mi respuesta aquí:

    Dado e como en:

    Enum e = Question.Role;

    A continuación, estos trabajos:

    int i = Convert.ToInt32(e);
    int i = (int)(object)e;
    int i = (int)Enum.Parse(e.GetType(), e.ToString());
    int i = (int)Enum.ToObject(e.GetType(), e);

    Los dos últimos son bastante desagradable. El primero de ellos debería ser más legible, a pesar de que el segundo es mucho más rápido. O puede ser un método de extensión es la mejor, mejor de ambos mundos.

    public static int GetIntValue(this Enum e)
    {
        return e.GetValue<int>();
    }
    
    public static T GetValue<T>(this Enum e) where T : struct, IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T>
    {
        return (T)(object)e;
    }

    Ahora usted puede llamar a:

    e.GetValue<int>(); //or
    e.GetIntValue();
    • Está usted seguro de que el segundo es más rápido? Supongo que será la caja de la enumeración y, a continuación, unbox de vuelta a int?
    • el e variable ya tiene la caja instancia de real tipo de valor, es decir, enum. Cuando usted escribe Enum e = Question.Role; ya está en caja. La pregunta es acerca de la conversión de la caja System.Enum de vuelta a subyacentes de tipo int (unboxing). Así que aquí unboxing es sólo el rendimiento de preocupación. (int)(object)e es directa unbox llamada; sí debe ser más rápido que otros enfoques. Ver esta
    • gracias por la explicación. Yo estaba bajo la impresión equivocada de que una instancia de Sistema.Enum era un sin embalaje valor. Ver esta demasiado — msdn.microsoft.com/en-us/library/aa691158(v=vs 71).aspx
    • hmm sí. La cita relevante desde el link: De cualquier enumeración de tipo para el tipo de Sistema.Enum.
  6. 1

    La conversión de un System.Enum a un int funciona muy bien para mí (también en el MSDN). Tal vez es una Resharper error.

    • ¿Qué versión de tiempo de ejecución usando?
    • el enlace muestra la conversión de los sub tipos de System.Enum, no System.Enum sí mismo.
    • Un problema similar lo que tenía era un Resharper caché de bodrio. El cierre de VS y la eliminación de la Resharper caché cometió el error desaparece, incluso después de que nueva búsqueda completa.
  7. 1

    Desde las Enumeraciones son restringidos a byte, sbyte, short, ushort, int, uint, long y ulong, podemos hacer algunas suposiciones.

    Podemos evitar excepciones durante la conversión mediante el uso de la más grande disponible contenedor. Por desgracia, que el recipiente a utilizar no es clara debido a ulong va a explotar para los números negativos y el tiempo va a volar por los números entre el largo.MaxValue y ulong.MaxValue. Necesitamos para alternar entre estas opciones en función del tipo subyacente.

    Por supuesto, usted todavía tiene que decidir qué hacer cuando el resultado no se ajusta dentro de un int. Creo que el casting está bien, pero todavía hay algunas trampas:

    1. para las enumeraciones, basada en un tipo con un espacio mayor que int (a largo y ulong), es posible que algunas de las enumeraciones evaluará el mismo valor.
    2. la fundición de un número mayor de int.MaxValue producirá una excepción si usted está en una región marcada.

    Esta es mi sugerencia, lo voy a dejar al lector decidir donde exponer esta función; como un ayudante o una extensión.

    public int ToInt(Enum e)
    {
      unchecked
      {
        if (e.GetTypeCode() == TypeCode.UInt64)
          return (int)Convert.ToUInt64(e);
        else
          return (int)Convert.ToInt64(e);
      }
    }
  8. -1

    No olvides que el tipo Enum en sí tiene un montón de funciones auxiliares estáticos en ella. Si todo lo que quiero hacer es convertir una instancia de la enumeración de su correspondiente tipo entero, entonces casting es probablemente la manera más eficiente.

    Creo que ReSharper se queja porque la Enumeración no es una enumeración de ningún tipo en particular, y las enumeraciones de ellos derivan de un escalar valuetype, no Enum. Si usted necesita adaptable casting de una manera genérica, yo diría que esto podría suite bien (tenga en cuenta que el tipo de enumeración en sí también está incluido en el genérico:

    public static EnumHelpers
    {
        public static T Convert<T, E>(E enumValue)
        {
            return (T)enumValue;
        }
    }

    Esto podría ser utilizado como:

    public enum StopLight: int
    {
        Red = 1,
        Yellow = 2,
        Green = 3
    }
    
    //...
    
    int myStoplightColor = EnumHelpers.Convert<int, StopLight>(StopLight.Red);

    Yo puedo decir con certeza que la parte superior de mi cabeza, pero el código anterior podría incluso ser apoyado por C#’s de la inferencia de tipos, lo que permite las siguientes:

    int myStoplightColor = EnumHelpers.Convert<int>(StopLight.Red);
    • Por desgracia, en su ejemplo E puede ser de cualquier tipo. Genéricos no me permite utilizar Enum como parámetro de tipo de restricción. No puedo decir: donde: T : Enum
    • Usted podría utilizar donde T: struct, aunque. Su no es tan estricta como usted quiere que sea, pero sería cortar cualquier tipo de referencia (que creo que es lo que tu tratando de hacer.)
    • usted puede usar: if (!typeof(E).IsEnum) throw new ArgumentException(«E debe ser de un tipo enumerado»);
    • Esto no es ni remotamente correcta, la auxiliar estática no es válido.
    • ¿Por qué debería alguien uso EnumHelpers.Convert<int, StopLight>(StopLight.Red); en lugar de (int)StopLight.Read;? También la cuestión está hablando acerca de System.Enum.

Dejar respuesta

Please enter your comment!
Please enter your name here