Il tipo enum, come descrive il suo nome, è un enumeratore di valori costanti. L'enum aggiunge anche espressività al nostro codice, e a volte è pratico utilizzarlo anche in presenza di un attributo o un parametro che può assumere solo due valori piuttosto che utilizzare il "semplice" tipo bool. Di seguito riporto alcuni esempi di codice che uso per estendere le informazioni del tipo enum, per convertirlo in una tupla di valori e per utilizzarlo in un controllo ComboBox.

E' possibile utilizzare l'attributo [Description(description)] per associare una descrizione ad ogni valore dell'enumeratore:

public enum TestEnum

{

  Value1,

   [Description("This is value 2")]

  Value2

}

Definendo un opportuno Extension Method è possibile aggiungere un nuovo metodo GetDescription() al valore dell'enum per estrarre la descrizione, se disponibile perchè definito l'attributo [Description("...")]:

public static class UtilsEnum

{

  public static string GetDescription(this Enum en)

  {

    Type type = en.GetType();

 

    MemberInfo[] memInfo = type.GetMember(en.ToString());

 

    if (memInfo != null && memInfo.Length > 0)

    {

      DescriptionAttribute descriptionAttribute =

      Attribute.GetCustomAttribute(memInfo[0], typeof (DescriptionAttribute), true) as DescriptionAttribute;

 

      if (descriptionAttribute!=null)

        return descriptionAttribute.Description;

    }

 

    return en.ToString();

  }

}

Ecco come funziona il metodo visto attraverso due unit test:

[TestClass]

public class UtilsEnumTest

{

   [TestMethod]

  public void WhenEnumHasNotDescriptionAttributeGetDescriptionReturnValueAsString()

   {

    Assert.AreEqual("Value1", TestEnum.Value1.GetDescript());]

   }

 

   [TestMethod

  public void WhenEnumHasDescriptionAttributeGetDescriptionReturnDescription()

  {

    Assert.AreEqual("This is value 2", TestEnum.Value2.GetDescription());

  }

}

A questo punto è possibile scrivere un metodo per convirtire un tipo enum in una Lista di tuple valore-descrizione, funzione utile per poter effettuare il binding dell'enumeratore su controlli di interfaccia utente:

public static class UtilsEnum

{

  public static List<Tuple<ENUM_TYPE,string>> GetEnumTupleValues<ENUM_TYPE>()

  {

    List<Tuple<ENUM_TYPE,string>> tuples = new List<Tuple<ENUM_TYPE, string>>();

 

    foreach (object value in Enum.GetValues(typeof (ENUM_TYPE)))

      tuples.Add(new Tuple<ENUM_TYPE, string>((ENUM_TYPE) value, ((Enum) value).GetDescription()));

 

    return tuples;

  }

}

Di seguito un test che illustra il funzionamento del metodo GetEnumTupleValues<ENUM_TYPE>(): (Nota: UtilsCollection.AreEquals è un metodo di utility che confronta due liste (generics List<T>) e ritorna true se sono uguali)

[TestClass]

public class UtilsEnumTest

{

  [TestMethod]

  public void EnumTuplesContainAllEnumValuesAndDescription()

  {

    List<Tuple<TestEnum, string>> expected = new List<Tuple<TestEnum, string>>()

                                       {

                                       new Tuple<TestEnum, string>(TestEnum.Value1,

                                                                   TestEnum.Value1.GetDescription()),

                                       new Tuple<TestEnum, string>(TestEnum.Value2,

                                                                   TestEnum.Value2.GetDescription())

                                       };

 

     List<Tuple<TestEnum, string>> tuples = utils.UtilsEnum.GetEnumTupleValues<TestEnum>();

 

     Assert.IsTrue(UtilsCollection.AreEquals(expected, tuples));

  }

}

Ecco quindi un uso tipico in una applicazione Windows Forms, dove è stato inserito un combo-box e una label che visualizza la scelta effettuata, le opzioni della combo sono quindi alimentate da un enumeratore.

Per effettuare il binding del combo-box è sufficiente assegnare alla proprietà DataSource le tuple generate con la funzione GetEnumTupleValues<ENUM_TYPE>() e quindi impostare le proprietà ValueMember e DisplayMember rispettivamente a "Item1" e "Item2" che corrispondono alle proprietà esposte dall'interfaccia della classe Tuple<T1,T2>. Per sapere il valore corrispondente dell'enum selezionato sul combo-box è sufficente utilizzare la proprietà SelectedValue la quale, può essere convertita al tipo dell'enumeratore. Di seguito il codice dell'applicazione di esempio:

public partial class Form1 : Form

{

  private void Form1_Load(object sender, EventArgs e)

  {

    cmbEnumTest.DataSource = UtilsEnum.GetEnumTupleValues<Opzioni>();

    cmbEnumTest.ValueMember = "Item1";

    cmbEnumTest.DisplayMember = "Item2";

  }

 

  public enum Opzioni

  {

    [Description("Prima opzione")]

    OpzioneA,

    [Description("Opzione avanzata")]

    OpzioneB,

    [Description("Opzione semplice")]

    OpzioneC,

    [Description("Ultima opzione")]

    OpzioneZ

  }

 

  private void cmbEnumTest_SelectedIndexChanged(object sender, EventArgs e)

  {

    lblSelected.Text = cmbEnumTest.SelectedValue.ToString();

  }

}