web-dev-qa-db-fra.com

Comment convertir une énumération en liste en C #?

Est-il possible de convertir un enum en une liste contenant toutes les options de l'énum?

558
newWeb

Cela retournera un IEnumerable<SomeEnum> de toutes les valeurs d'un Enum.

Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>();

Si vous voulez que ce soit un List<SomeEnum>, ajoutez simplement .ToList() après .Cast<SomeEnum>().

Pour utiliser la fonction Cast sur un tableau, vous devez avoir le System.Linq dans votre section using.

965
Jake Pearson

Manière beaucoup plus facile:

Enum.GetValues(typeof(SomeEnum))
    .Cast<SomeEnum>()
    .Select(v => v.ToString())
    .ToList();
98
Gili

La réponse courte est, utilisez:

(SomeEnum[])Enum.GetValues(typeof(SomeEnum))

Si vous avez besoin de cela pour une variable locale, c'est var allSomeEnumValues = (SomeEnum[])Enum.GetValues(typeof(SomeEnum));.

Pourquoi la syntaxe est-elle la suivante?!

La méthode staticGetValues a été réintroduite dans les anciens jours .NET 1.0. Il retourne un tableau unidimensionnel de type à l'exécution SomeEnum[]. Mais comme il s'agit d'une méthode non générique (les génériques n'ont pas été introduits avant .NET 2.0), il ne peut pas déclarer son type de retour (type de retour à la compilation) en tant que tel.

Les tableaux .NET ont une sorte de covariance, mais parce que SomeEnum sera un type (-) et Comme la covariance des types de tableaux ne fonctionne pas avec les types de valeur, ils ne pouvaient même pas déclarer le type de retour sous la forme object[] ou Enum[]. (Ceci est différent de par exemple cette surcharge de GetCustomAttributes from .NET 1. qui a le type de retour à la compilation object[] mais renvoie en réalité un tableau de type SomeAttribute[]SomeAttribute est nécessairement un Type de référence.)

De ce fait, la méthode .NET 1.0 devait déclarer son type de retour sous la forme System.Array. Mais je vous garantis que c’est un SomeEnum[].

Chaque fois que vous appelez à nouveau GetValues avec le même type enum, il devra allouer un nouveau tableau et copier les valeurs dans le nouveau tableau. Cela est dû au fait que les tableaux peuvent être modifiés (modifiés) par le "consommateur" de la méthode, ils doivent donc créer un nouveau tableau pour être sûrs que les valeurs sont inchangées. .NET 1.0 n'avait pas de bonnes collections en lecture seule.

Si vous avez besoin de la liste de toutes les valeurs à plusieurs endroits différents, envisagez d'appeler GetValues une seule fois et mettez le résultat en cache dans un wrapper en lecture seule, par exemple:

public static readonly ReadOnlyCollection<SomeEnum> AllSomeEnumValues
    = Array.AsReadOnly((SomeEnum[])Enum.GetValues(typeof(SomeEnum)));

Ensuite, vous pouvez utiliser AllSomeEnumValues plusieurs fois et la même collection peut être réutilisée en toute sécurité.

Pourquoi est-il mauvais d'utiliser .Cast<SomeEnum>()?

Beaucoup d'autres réponses utilisent .Cast<SomeEnum>(). Le problème, c'est qu'il utilise l'implémentation non générique IEnumerable de la classe Array. Cela aurait dû impliquer la mise en boîte de chacune des valeurs dans une zone System.Object, puis l'utilisation de la méthode Cast<> pour décompresser à nouveau toutes ces valeurs. Heureusement, la méthode .Cast<> semble vérifier le type d'exécution de son paramètre IEnumerable (paramètre this) avant de commencer à parcourir la collection, de sorte qu'il n'est pas si mal après tout. .Cast<> laisse passer la même instance de tableau.

Si vous le suivez par .ToArray() ou .ToList(), comme dans:

Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>().ToList() // DON'T do this

vous avez un autre problème: vous créez une nouvelle collection (tableau) lorsque vous appelez GetValues, puis créez une nouvelle collection (List<>) avec l'appel .ToList(). Il s’agit donc d’une allocation redondante (supplémentaire) de toute une collection pour conserver les valeurs.

76

Voici comment j'aime utiliser LINQ:

public class EnumModel
{
    public int Value { get; set; }
    public string Name { get; set; }
}

public enum MyEnum
{
    Name1=1,
    Name2=2,
    Name3=3
}

public class Test
{
        List<EnumModel> enums = ((MyEnum[])Enum.GetValues(typeof(MyEnum))).Select(c => new EnumModel() { Value = (int)c, Name = c.ToString() }).ToList();

        // A list of Names only, does away with the need of EnumModel 
        List<string> MyNames = ((MyEnum[])Enum.GetValues(typeof(MyEnum))).Select(c => c.ToString()).ToList();

        // A list of Values only, does away with the need of EnumModel 
        List<int> myValues = ((MyEnum[])Enum.GetValues(typeof(MyEnum))).Select(c => (int)c).ToList();

        // A dictionnary of <string,int>
        Dictionary<string,int> myDic = ((MyEnum[])Enum.GetValues(typeof(MyEnum))).ToDictionary(k => k.ToString(), v => (int)v);
}

J'espère que ça aide

29
Booster2ooo
List <SomeEnum> theList = Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>().ToList();
20
luisetxenike

réponse très simple

Voici une propriété que j'utilise dans l'une de mes applications

public List<string> OperationModes
{
    get
    {
       return Enum.GetNames(typeof(SomeENUM)).ToList();
    }
}
11
Tyler
Language[] result = (Language[])Enum.GetValues(typeof(Language))
5
Shyam sundar shah

J'ai toujours eu l'habitude d'obtenir une liste de valeurs enum comme celle-ci:

Array list = Enum.GetValues(typeof (SomeEnum));
5
Claudiu Constantin

Voici pour l'utilité ... du code pour obtenir les valeurs dans une liste, qui convertit l'énum en forme lisible pour le texte

public class KeyValuePair
  {
    public string Key { get; set; }

    public string Name { get; set; }

    public int Value { get; set; }

    public static List<KeyValuePair> ListFrom<T>()
    {
      var array = (T[])(Enum.GetValues(typeof(T)).Cast<T>());
      return array
        .Select(a => new KeyValuePair
          {
            Key = a.ToString(),
            Name = a.ToString().SplitCapitalizedWords(),
            Value = Convert.ToInt32(a)
          })
          .OrderBy(kvp => kvp.Name)
         .ToList();
    }
  }

.. et la méthode d'extension System.String associée:

/// <summary>
/// Split a string on each occurrence of a capital (assumed to be a Word)
/// e.g. MyBigToe returns "My Big Toe"
/// </summary>
public static string SplitCapitalizedWords(this string source)
{
  if (String.IsNullOrEmpty(source)) return String.Empty;
  var newText = new StringBuilder(source.Length * 2);
  newText.Append(source[0]);
  for (int i = 1; i < source.Length; i++)
  {
    if (char.IsUpper(source[i]))
      newText.Append(' ');
    newText.Append(source[i]);
  }
  return newText.ToString();
}
5
public class NameValue
{
    public string Name { get; set; }
    public object Value { get; set; }
}

public class NameValue
{
    public string Name { get; set; }
    public object Value { get; set; }
}

public static List<NameValue> EnumToList<T>()
{
    var array = (T[])(Enum.GetValues(typeof(T)).Cast<T>()); 
    var array2 = Enum.GetNames(typeof(T)).ToArray<string>(); 
    List<NameValue> lst = null;
    for (int i = 0; i < array.Length; i++)
    {
        if (lst == null)
            lst = new List<NameValue>();
        string name = array2[i];
        T value = array[i];
        lst.Add(new NameValue { Name = name, Value = value });
    }
    return lst;
}

Convert Enum À une liste plus d'informations disponibles ici .

4
Kiarash
private List<SimpleLogType> GetLogType()
{
  List<SimpleLogType> logList = new List<SimpleLogType>();
  SimpleLogType internalLogType;
  foreach (var logtype in Enum.GetValues(typeof(Log)))
  {
    internalLogType = new SimpleLogType();
    internalLogType.Id = (int) (Log) Enum.Parse(typeof (Log), logtype.ToString(), true);
    internalLogType.Name = (Log)Enum.Parse(typeof(Log), logtype.ToString(), true);
    logList.Add(internalLogType);
  }
  return logList;
}

dans Code, Log est un enum et SimpleLogType est une structure pour les journaux.

public enum Log
{
  None = 0,
  Info = 1,
  Warning = 8,
  Error = 3
}
2
/// <summary>
/// Method return a read-only collection of the names of the constants in specified enum
/// </summary>
/// <returns></returns>
public static ReadOnlyCollection<string> GetNames()
{
    return Enum.GetNames(typeof(T)).Cast<string>().ToList().AsReadOnly();   
}

T est un type d'énumération; Ajoute ça:

using System.Collections.ObjectModel; 
1
frigate

Si vous voulez Enum int en tant que clé et nom en tant que valeur, c'est bien si vous stockez le numéro dans la base de données et qu'il provient d'Enum!

void Main()
{
     ICollection<EnumValueDto> list = EnumValueDto.ConvertEnumToList<SearchDataType>();

     foreach (var element in list)
     {
        Console.WriteLine(string.Format("Key: {0}; Value: {1}", element.Key, element.Value));
     }

     /* OUTPUT:
        Key: 1; Value: Boolean
        Key: 2; Value: DateTime
        Key: 3; Value: Numeric         
     */
}

public class EnumValueDto
{
    public int Key { get; set; }

    public string Value { get; set; }

    public static ICollection<EnumValueDto> ConvertEnumToList<T>() where T : struct, IConvertible
    {
        if (!typeof(T).IsEnum)
        {
            throw new Exception("Type given T must be an Enum");
        }

        var result = Enum.GetValues(typeof(T))
                         .Cast<T>()
                         .Select(x =>  new EnumValueDto { Key = Convert.ToInt32(x), 
                                       Value = x.ToString(new CultureInfo("en")) })
                         .ToList()
                         .AsReadOnly();

        return result;
    }
}

public enum SearchDataType
{
    Boolean = 1,
    DateTime,
    Numeric
}
1
xajler

Vous pouvez utiliser la méthode générique suivante:

public static List<T> GetItemsList<T>(this int enums) where T : struct, IConvertible
{
    if (!typeof (T).IsEnum)
    {
        throw new Exception("Type given must be an Enum");
    }

    return (from int item in Enum.GetValues(typeof (T))
            where (enums & item) == item
            select (T) Enum.Parse(typeof (T), item.ToString(new CultureInfo("en")))).ToList();
}
0
Vitall