Leer en inglés

Compartir a través de


Clase System.Enum

En este artículo se proporcionan comentarios adicionales a la documentación de referencia de esta API.

Una enumeración es un conjunto de constantes con nombre cuyo tipo subyacente es cualquier tipo entero. Si no se declara explícitamente ningún tipo subyacente, Int32 se usa. Enum es la clase base para todas las enumeraciones de .NET. Los tipos de enumeración se definen mediante la enum palabra clave en C#, la Enumconstrucción ...End Enum en Visual Basic y la type palabra clave en F#.

Enum proporciona métodos para comparar instancias de esta clase, convertir el valor de una instancia en su representación de cadena, convertir la representación de cadena de un número en una instancia de esta clase y crear una instancia de una enumeración y un valor especificados.

También puede tratar una enumeración como un campo de bits. Para obtener más información, vea la sección Miembros no exclusivos y el atributo Flags y FlagsAttribute.

Creación de un tipo de enumeración

Los lenguajes de programación suelen proporcionar sintaxis para declarar una enumeración que consta de un conjunto de constantes con nombre y sus valores. En el ejemplo siguiente se muestra la sintaxis usada por C#, F#y Visual Basic para definir una enumeración. Crea una enumeración denominada ArrivalStatus que tiene tres miembros: ArrivalStatus.Early, ArrivalStatus.OnTimey ArrivalStatus.Late. Tenga en cuenta que, en todos los casos, la enumeración no hereda explícitamente de ; el compilador controla implícitamente la relación de Enumherencia.

C#
public enum ArrivalStatus { Unknown=-3, Late=-1, OnTime=0, Early=1 };

Advertencia

Nunca debe crear un tipo de enumeración cuyo tipo subyacente no sea entero o Char. Aunque puede crear este tipo de enumeración mediante la reflexión, las llamadas al método que usan el tipo resultante no son confiables y también pueden producir excepciones adicionales.

Creación de instancias de un tipo de enumeración

Puede crear una instancia de un tipo de enumeración igual que crear instancias de cualquier otro tipo de valor: declarando una variable y asignando una de las constantes de la enumeración. En el ejemplo siguiente se crea una instancia de cuyo ArrivalStatus valor es ArrivalStatus.OnTime.

C#
public class Example
{
   public static void Main()
   {
      ArrivalStatus status = ArrivalStatus.OnTime;
      Console.WriteLine("Arrival Status: {0} ({0:D})", status);
   }
}
// The example displays the following output:
//       Arrival Status: OnTime (0)

También puede crear una instancia de un valor de enumeración de las maneras siguientes:

  • Mediante el uso de características de un lenguaje de programación determinado para convertir (como en C#) o convertir (como en Visual Basic) un valor entero en un valor de enumeración. En el ejemplo siguiente se crea un ArrivalStatus objeto cuyo valor está ArrivalStatus.Early de esta manera.

    C#
    ArrivalStatus status2 = (ArrivalStatus)1;
    Console.WriteLine("Arrival Status: {0} ({0:D})", status2);
    // The example displays the following output:
    //       Arrival Status: Early (1)
    
  • Mediante una llamada a su constructor sin parámetros implícito. Como se muestra en el ejemplo siguiente, en este caso el valor subyacente de la instancia de enumeración es 0. Sin embargo, esto no es necesariamente el valor de una constante válida en la enumeración.

    C#
    ArrivalStatus status1 = new ArrivalStatus();
    Console.WriteLine("Arrival Status: {0} ({0:D})", status1);
    // The example displays the following output:
    //       Arrival Status: OnTime (0)
    
  • Llamando al Parse método o TryParse para analizar una cadena que contiene el nombre de una constante en la enumeración. Para obtener más información, consulte la sección Análisis de valores de enumeración.

  • Llamando al ToObject método para convertir un valor entero en un tipo de enumeración. Para obtener más información, consulte la sección Realizar conversiones .

Procedimientos recomendados de enumeración

Se recomienda usar los procedimientos recomendados siguientes al definir tipos de enumeración:

  • Si no ha definido un miembro de enumeración cuyo valor es 0, considere la posibilidad de crear una None constante enumerada. De forma predeterminada, la memoria usada para la enumeración se inicializa en cero por Common Language Runtime. Por lo tanto, si no define una constante cuyo valor es cero, la enumeración contendrá un valor no válido cuando se cree.

  • Si hay un caso predeterminado obvio que la aplicación tiene que representar, considere la posibilidad de usar una constante enumerada cuyo valor es cero para representarlo. Si no hay ningún caso predeterminado, considere la posibilidad de usar una constante enumerada cuyo valor es cero para especificar el caso que no está representado por ninguna de las otras constantes enumeradas.

  • No especifique constantes enumeradas reservadas para uso futuro.

  • Al definir un método o propiedad que toma una constante enumerada como un valor, considere la posibilidad de validar el valor. El motivo es que puede convertir un valor numérico al tipo de enumeración aunque ese valor numérico no esté definido en la enumeración.

Los procedimientos recomendados adicionales para los tipos de enumeración cuyas constantes son campos de bits se enumeran en la sección Miembros no exclusivos y el atributo Flags.

Realización de operaciones con enumeraciones

No se pueden definir nuevos métodos al crear una enumeración. Sin embargo, un tipo de enumeración hereda un conjunto completo de métodos estáticos e de instancia de la Enum clase . Las secciones siguientes analizan la mayoría de estos métodos, además de otros métodos que se usan habitualmente al trabajar con valores de enumeración.

Realizar conversiones

Puede convertir entre un miembro de enumeración y su tipo subyacente mediante una conversión (en C# y F#) o un operador de conversión (en Visual Basic). En F#, también se usa la enum función . En el ejemplo siguiente se usan operadores de conversión o conversión para realizar conversiones de un entero a un valor de enumeración y de un valor de enumeración a un entero.

C#
int value3 = 2;
ArrivalStatus status3 = (ArrivalStatus)value3;

int value4 = (int)status3;

La Enum clase también incluye un ToObject método que convierte un valor de cualquier tipo entero en un valor de enumeración. En el ejemplo siguiente se usa el ToObject(Type, Int32) método para convertir un Int32 objeto en un ArrivalStatus valor. Tenga en cuenta que, dado ToObject que devuelve un valor de tipo Object, el uso de un operador de conversión o conversión puede ser necesario para convertir el objeto al tipo de enumeración.

C#
int number = -1;
ArrivalStatus arrived = (ArrivalStatus)ArrivalStatus.ToObject(typeof(ArrivalStatus), number);

Al convertir un entero en un valor de enumeración, es posible asignar un valor que realmente no sea miembro de la enumeración. Para evitar esto, puede pasar el entero al IsDefined método antes de realizar la conversión. En el ejemplo siguiente se usa este método para determinar si los elementos de una matriz de valores enteros se pueden convertir en ArrivalStatus valores.

C#
using System;

public class Example3
{
    public static void Main()
    {
        int[] values = { -3, -1, 0, 1, 5, Int32.MaxValue };
        foreach (var value in values)
        {
            ArrivalStatus status;
            if (Enum.IsDefined(typeof(ArrivalStatus), value))
                status = (ArrivalStatus)value;
            else
                status = ArrivalStatus.Unknown;
            Console.WriteLine("Converted {0:N0} to {1}", value, status);
        }
    }
}
// The example displays the following output:
//       Converted -3 to Unknown
//       Converted -1 to Late
//       Converted 0 to OnTime
//       Converted 1 to Early
//       Converted 5 to Unknown
//       Converted 2,147,483,647 to Unknown

Aunque la Enum clase proporciona implementaciones de interfaz explícitas de la IConvertible interfaz para convertir de un valor de enumeración a un tipo entero, debe usar los métodos de la Convert clase , como ToInt32, para realizar estas conversiones. En el ejemplo siguiente se muestra cómo puede usar el GetUnderlyingType método junto con el Convert.ChangeType método para convertir un valor de enumeración en su tipo subyacente. Tenga en cuenta que este ejemplo no requiere que el tipo subyacente de la enumeración se conozca en tiempo de compilación.

C#
ArrivalStatus status = ArrivalStatus.Early;
var number = Convert.ChangeType(status, Enum.GetUnderlyingType(typeof(ArrivalStatus)));
Console.WriteLine("Converted {0} to {1}", status, number);
// The example displays the following output:
//       Converted Early to 1

Análisis de los valores de enumeración

Los Parse métodos y TryParse permiten convertir la representación de cadena de un valor de enumeración en ese valor. La representación de cadena puede ser el nombre o el valor subyacente de una constante de enumeración. Tenga en cuenta que los métodos de análisis convertirán correctamente representaciones de cadena de números que no son miembros de una enumeración determinada si las cadenas se pueden convertir en un valor del tipo subyacente de la enumeración. Para evitar esto, se puede llamar al IsDefined método para asegurarse de que el resultado del método de análisis es un valor de enumeración válido. En el ejemplo se muestra este enfoque y se muestran las llamadas a los Parse(Type, String) métodos y Enum.TryParse<TEnum>(String, TEnum) . Tenga en cuenta que el método de análisis no genérico devuelve un objeto que puede tener que convertir (en C# y F#) o convertir (en Visual Basic) al tipo de enumeración adecuado.

C#
string number = "-1";
string name = "Early";

try
{
    ArrivalStatus status1 = (ArrivalStatus)Enum.Parse(typeof(ArrivalStatus), number);
    if (!(Enum.IsDefined(typeof(ArrivalStatus), status1)))
        status1 = ArrivalStatus.Unknown;
    Console.WriteLine("Converted '{0}' to {1}", number, status1);
}
catch (FormatException)
{
    Console.WriteLine("Unable to convert '{0}' to an ArrivalStatus value.",
                      number);
}

ArrivalStatus status2;
if (Enum.TryParse<ArrivalStatus>(name, out status2))
{
    if (!(Enum.IsDefined(typeof(ArrivalStatus), status2)))
        status2 = ArrivalStatus.Unknown;
    Console.WriteLine("Converted '{0}' to {1}", name, status2);
}
else
{
    Console.WriteLine("Unable to convert '{0}' to an ArrivalStatus value.",
                      number);
}
// The example displays the following output:
//       Converted '-1' to Late
//       Converted 'Early' to Early

Formato de valores de enumeración

Puede convertir los valores de enumeración en sus representaciones de cadena llamando al método estático Format , así como a las sobrecargas del método de instancia ToString . Puede usar una cadena de formato para controlar la forma precisa en que un valor de enumeración se representa como una cadena. Para obtener más información, vea Enumeration Format Strings( Cadenas de formato de enumeración). En el ejemplo siguiente se usa cada una de las cadenas de formato de enumeración admitidas ("G" o "g", "D" o "d", "X" o "x" y "F" o "f" ) para convertir un miembro de la ArrivalStatus enumeración en sus representaciones de cadena.

C#
string[] formats = { "G", "F", "D", "X" };
ArrivalStatus status = ArrivalStatus.Late;
foreach (var fmt in formats)
    Console.WriteLine(status.ToString(fmt));

// The example displays the following output:
//       Late
//       Late
//       -1
//       FFFFFFFF

Iterar miembros de enumeración

El Enum tipo no implementa la IEnumerable interfaz o IEnumerable<T> , lo que le permitiría iterar miembros de una colección mediante una foreach construcción (en C#), for..in (en F#) o For Each (en Visual Basic). Sin embargo, puede enumerar miembros de dos maneras.

  • Puede llamar al GetNames método para recuperar una matriz de cadenas que contenga los nombres de los miembros de enumeración. A continuación, para cada elemento de la matriz de cadenas, puede llamar al Parse método para convertir la cadena en su valor de enumeración equivalente. En el ejemplo siguiente se muestra este enfoque.

    C#
    string[] names = Enum.GetNames(typeof(ArrivalStatus));
    Console.WriteLine("Members of {0}:", typeof(ArrivalStatus).Name);
    Array.Sort(names);
    foreach (var name in names)
    {
        ArrivalStatus status = (ArrivalStatus)Enum.Parse(typeof(ArrivalStatus), name);
        Console.WriteLine("   {0} ({0:D})", status);
    }
    // The example displays the following output:
    //       Members of ArrivalStatus:
    //          Early (1)
    //          Late (-1)
    //          OnTime (0)
    //          Unknown (-3)
    
  • Puede llamar al GetValues método para recuperar una matriz que contenga los valores subyacentes de la enumeración. A continuación, para cada elemento de la matriz, puede llamar al ToObject método para convertir el entero en su valor de enumeración equivalente. En el ejemplo siguiente se muestra este enfoque.

    C#
    var values = Enum.GetValues(typeof(ArrivalStatus));
    Console.WriteLine("Members of {0}:", typeof(ArrivalStatus).Name);
    foreach (ArrivalStatus status in values)
    {
        Console.WriteLine("   {0} ({0:D})", status);
    }
    // The example displays the following output:
    //       Members of ArrivalStatus:
    //          OnTime (0)
    //          Early (1)
    //          Unknown (-3)
    //          Late (-1)
    

Miembros no exclusivos y el atributo Flags

Un uso común de una enumeración es representar un conjunto de valores mutuamente excluyentes. Por ejemplo, una ArrivalStatus instancia puede tener un valor de Early, OnTimeo Late. No tiene sentido que el valor de una ArrivalStatus instancia refleje más de una constante de enumeración.

Sin embargo, en otros casos, el valor de un objeto de enumeración puede incluir varios miembros de enumeración y cada miembro representa un campo de bits en el valor de enumeración. El FlagsAttribute atributo se puede usar para indicar que la enumeración consta de campos de bits. Por ejemplo, una enumeración denominada Pets podría usarse para indicar los tipos de mascotas en un hogar. Se puede definir de la manera siguiente.

C#
[Flags]
public enum Pets
{
    None = 0, Dog = 1, Cat = 2, Bird = 4, Rodent = 8,
    Reptile = 16, Other = 32
};

A Pets continuación, la enumeración se puede usar como se muestra en el ejemplo siguiente.

C#
Pets familyPets = Pets.Dog | Pets.Cat;
Console.WriteLine("Pets: {0:G} ({0:D})", familyPets);
// The example displays the following output:
//       Pets: Dog, Cat (3)

Se deben usar los procedimientos recomendados siguientes al definir una enumeración bit a bit y aplicar el FlagsAttribute atributo .

  • Use el FlagsAttribute atributo personalizado para una enumeración solo si se va a realizar una operación bit a bit (AND, OR, EXCLUSIVE OR) en un valor numérico.

  • Defina constantes de enumeración en potencias de dos, es decir, 1, 2, 4, 8, etc. Esto significa que las marcas individuales de las constantes de enumeración combinadas no se superponen.

  • Considere la posibilidad de crear una constante enumerada para combinaciones de marcas usadas habitualmente. Por ejemplo, si tiene una enumeración usada para las operaciones de E/S de archivo que contiene las constantes enumeradas Read = 1 y Write = 2, considere la posibilidad de crear la constante ReadWrite = Read OR Writeenumerada , que combina las Read marcas y Write . Además, la operación OR bit a bit usada para combinar las marcas podría considerarse un concepto avanzado en algunas circunstancias que no deberían ser necesarias para tareas simples.

  • Tenga cuidado si define un número negativo como una constante enumerada de marca porque muchas posiciones de marca pueden establecerse en 1, lo que podría hacer que el código sea confuso y fomentar errores de codificación.

  • Una manera cómoda de probar si una marca está establecida en un valor numérico es llamar al método de instancia HasFlag , como se muestra en el ejemplo siguiente.

    C#
    Pets familyPets = Pets.Dog | Pets.Cat;
    if (familyPets.HasFlag(Pets.Dog))
        Console.WriteLine("The family has a dog.");
    // The example displays the following output:
    //       The family has a dog.
    

    Equivale a realizar una operación AND bit a bit entre el valor numérico y la constante enumerada de marca, que establece todos los bits del valor numérico en cero que no corresponden a la marca y, a continuación, comprueba si el resultado de esa operación es igual a la constante enumerada de marca. Esto se muestra en el ejemplo siguiente.

    C#
    Pets familyPets = Pets.Dog | Pets.Cat;
    if ((familyPets & Pets.Dog) == Pets.Dog)
        Console.WriteLine("The family has a dog.");
    // The example displays the following output:
    //       The family has a dog.
    
  • Use None como nombre de la constante enumerada de marca cuyo valor es cero. No se puede usar la None constante enumerada en una operación AND bit a bit para probar una marca porque el resultado siempre es cero. Sin embargo, puede realizar una comparación lógica, no bit a bit, entre el valor numérico y la None constante enumerada para determinar si se establecen los bits del valor numérico. Esto se muestra en el ejemplo siguiente.

    C#
    Pets familyPets = Pets.Dog | Pets.Cat;
    if (familyPets == Pets.None)
        Console.WriteLine("The family has no pets.");
    else
        Console.WriteLine("The family has pets.");
    // The example displays the following output:
    //       The family has pets.
    
  • No defina un valor de enumeración únicamente para reflejar el estado de la propia enumeración. Por ejemplo, no defina una constante enumerada que simplemente marque el final de la enumeración. Si necesita determinar el último valor de la enumeración, compruebe explícitamente ese valor. Además, puede realizar una comprobación de intervalo para la primera y última constante enumerada si todos los valores del intervalo son válidos.

Adición de métodos de enumeración

Dado que las estructuras de lenguaje definen los tipos de enumeración, como enum (C#) y Enum (Visual Basic), no se pueden definir métodos personalizados para un tipo de enumeración distinto de los métodos heredados de la Enum clase . Sin embargo, puede usar métodos de extensión para agregar funcionalidad a un tipo de enumeración determinado.

En el ejemplo siguiente, la enumeración Grades representa las posibles calificaciones con letras que un alumno puede recibir en una clase. Un método de extensión denominado Passing se agrega al tipo Grades para que cada instancia de ese tipo "sepa" ahora si representa una calificación de aprobado o no. La Extensions clase también contiene una variable estática de lectura y escritura que define la calificación mínima de paso. El valor devuelto del Passing método de extensión refleja el valor actual de esa variable.

C#
using System;

// Define an enumeration to represent student grades.
public enum Grades { F = 0, D = 1, C = 2, B = 3, A = 4 };

// Define an extension method for the Grades enumeration.
public static class Extensions
{
    public static Grades minPassing = Grades.D;

    public static bool Passing(this Grades grade)
    {
        return grade >= minPassing;
    }
}

class Example8
{
    static void Main()
    {
        Grades g1 = Grades.D;
        Grades g2 = Grades.F;
        Console.WriteLine("{0} {1} a passing grade.", g1, g1.Passing() ? "is" : "is not");
        Console.WriteLine("{0} {1} a passing grade.", g2, g2.Passing() ? "is" : "is not");

        Extensions.minPassing = Grades.C;
        Console.WriteLine("\nRaising the bar!\n");
        Console.WriteLine("{0} {1} a passing grade.", g1, g1.Passing() ? "is" : "is not");
        Console.WriteLine("{0} {1} a passing grade.", g2, g2.Passing() ? "is" : "is not");
    }
}
// The exmaple displays the following output:
//       D is a passing grade.
//       F is not a passing grade.
//
//       Raising the bar!
//
//       D is not a passing grade.
//       F is not a passing grade.

Ejemplos

En el ejemplo siguiente se muestra cómo usar una enumeración para representar valores con nombre y otra enumeración para representar campos de bits con nombre.

C#
using System;

public class EnumTest {
    enum Days { Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday };
    enum BoilingPoints { Celsius = 100, Fahrenheit = 212 };
    [Flags]
    enum Colors { Red = 1, Green = 2, Blue = 4, Yellow = 8 };

    public static void Main() {

        Type weekdays = typeof(Days);
        Type boiling = typeof(BoilingPoints);

        Console.WriteLine("The days of the week, and their corresponding values in the Days Enum are:");

        foreach ( string s in Enum.GetNames(weekdays) )
            Console.WriteLine( "{0,-11}= {1}", s, Enum.Format( weekdays, Enum.Parse(weekdays, s), "d"));

        Console.WriteLine();
        Console.WriteLine("Enums can also be created which have values that represent some meaningful amount.");
        Console.WriteLine("The BoilingPoints Enum defines the following items, and corresponding values:");

        foreach ( string s in Enum.GetNames(boiling) )
            Console.WriteLine( "{0,-11}= {1}", s, Enum.Format(boiling, Enum.Parse(boiling, s), "d"));

        Colors myColors = Colors.Red | Colors.Blue | Colors.Yellow;
        Console.WriteLine();
        Console.WriteLine("myColors holds a combination of colors. Namely: {0}", myColors);
    }
}