методы c# enum Как перечислить перечисление в C #?



13 Answers

Мне кажется, что вы действительно хотите распечатать имена каждого перечисления, а не значения. В этом случае Enum.GetNames() представляется правильным подходом.

public enum Suits
{
    Spades,
    Hearts,
    Clubs,
    Diamonds,
    NumSuits
}

public void PrintAllSuits()
{
    foreach (string name in Enum.GetNames(typeof(Suits)))
    {
        System.Console.WriteLine(name);
    }
}

Кстати, увеличение значения не является хорошим способом для перечисления значений перечисления. Вы должны это сделать.

Enum.GetValues(typeof(Suit)) я бы использовал Enum.GetValues(typeof(Suit)) .

public enum Suits
{
    Spades,
    Hearts,
    Clubs,
    Diamonds,
    NumSuits
}

public void PrintAllSuits()
{
    foreach (var suit in Enum.GetValues(typeof(Suits)))
    {
        System.Console.WriteLine(suit.ToString());
    }
}
enum c# примеры

Как вы можете перечислить enum в C #?

Например, следующий код не компилируется:

public enum Suit 
{
    Spades,
    Hearts,
    Clubs,
    Diamonds
}

public void EnumerateAllSuitsDemoMethod() 
{
    foreach (Suit suit in Suit) 
    {
        DoSomething(suit);
    }
}

И дает следующую ошибку времени компиляции:

«Костюм» - это «тип», но используется как «переменная»,

Он не Suit ключевого слова Suit , второго.




Некоторые версии .NET Framework не поддерживают Enum.GetValues . Вот хорошее обходное решение от Ideas 2.0: Enum.GetValues ​​в Compact Framework :

public List<Enum> GetValues(Enum enumeration)
{
   List<Enum> enumerations = new List<Enum>();
   foreach (FieldInfo fieldInfo in enumeration.GetType().GetFields(
         BindingFlags.Static | BindingFlags.Public))
   {
      enumerations.Add((Enum)fieldInfo.GetValue(enumeration));
   }
   return enumerations;
}

Как и любой код, который включает reflection , вы должны предпринять шаги, чтобы гарантировать, что он запускается только один раз, и результаты кэшируются.




Почему никто не использует Cast<T> ?

var suits = Enum.GetValues(typeof(Suit)).Cast<Suit>();

Там вы идете IEnumerable<Suit> .




Просто добавьте мое решение, которое работает в компактной структуре (3.5) и поддерживает проверку типов во время компиляции :

public static List<T> GetEnumValues<T>() where T : new() {
    T valueType = new T();
    return typeof(T).GetFields()
        .Select(fieldInfo => (T)fieldInfo.GetValue(valueType))
        .Distinct()
        .ToList();
}

public static List<String> GetEnumNames<T>() {
    return typeof (T).GetFields()
        .Select(info => info.Name)
        .Distinct()
        .ToList();
}

- Если кто-то знает, как избавиться от T valueType = new T() , я был бы рад увидеть решение.

Вызов будет выглядеть так:

List<MyEnum> result = Utils.GetEnumValues<MyEnum>();



public void PrintAllSuits()
{
    foreach(string suit in Enum.GetNames(typeof(Suits)))
    {
        Console.WriteLine(suit);
    }
}



Три способа:

1. Enum.GetValues(type) //since .NET 1.1, not in silverlight or compact framewok
2. type.GetEnumValues() //only on .NET 4 and above
3. type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)) //works everywhere

Не знаю, почему GetEnumValues был введен в экземпляр экземпляра, он для меня совсем не читается.

Наличие класса-помощника, такого как Enum<T> является для меня самым читаемым и запоминающимся:

public static class Enum<T> where T : struct, IComparable, IFormattable, IConvertible
{
    public static IEnumerable<T> GetValues()
    {
        return (T[])Enum.GetValues(typeof(T));
    }

    public static IEnumerable<string> GetNames()
    {
        return Enum.GetNames(typeof(T));
    }
}

Теперь вы вызываете:

Enum<Suit>.GetValues();
//or
Enum.GetValues(typeof(Suit)); //pretty consistent style

Также можно использовать кеширование, если производительность имеет значение, но я не ожидаю, что это будет проблемой вообще

public static class Enum<T> where T : struct, IComparable, IFormattable, IConvertible
{
    //lazily loaded
    static T[] values;
    static string[] names;

    public static IEnumerable<T> GetValues()
    {
        return values ?? (values = (T[])Enum.GetValues(typeof(T)));
    }

    public static IEnumerable<string> GetNames()
    {
        return names ?? (names = Enum.GetNames(typeof(T)));
    }
}



Я использую ToString (), затем разделяю и разбираю массив вершин в флагах.

[Flags]
public enum ABC {
   a = 1,
   b = 2,
   c = 4
};

public IEnumerable<ABC> Getselected (ABC flags)
{
   var values = flags.ToString().Split(',');
   var enums = values.Select(x => (ABC)Enum.Parse(typeof(ABC), x.Trim()));
   return enums;
}

ABC temp= ABC.a | ABC.b;
var list = getSelected (temp);
foreach (var item in list)
{
   Console.WriteLine(item.ToString() + " ID=" + (int)item);
}



Я не считаю, что это лучше или даже хорошо, просто заявив еще одно решение.

Если значения enum варьируются от 0 до n - 1, то общая альтернатива:

public void EnumerateEnum<T>()
{
    int length = Enum.GetValues(typeof(T)).Length;
    for (var i = 0; i < length; i++)
    {
        var @enum = (T)(object)i;
    }
}

Если значения перечисления смежны, и вы можете предоставить первый и последний элемент перечисления, тогда:

public void EnumerateEnum()
{
    for (var i = Suit.Spade; i <= Suit.Diamond; i++)
    {
        var @enum = i;
    }
}

но это не строго перечисление, просто цикл. Второй метод намного быстрее, чем любой другой подход, хотя ...




вот рабочий пример создания опций выбора для DDL

var resman = ViewModelResources.TimeFrame.ResourceManager;

ViewBag.TimeFrames = from MapOverlayTimeFrames timeFrame 
      in Enum.GetValues(typeof(MapOverlayTimeFrames))
      select new SelectListItem
      {
         Value = timeFrame.ToString(),
         Text = resman.GetString(timeFrame.ToString()) ?? timeFrame.ToString()
      };



Этот вопрос появляется в главе 10 « C # Step by Step 2013 »

Автор использует double for-loop для итерации через пару Enumerators (для создания полной колоды карт):

class Pack
{
    public const int NumSuits = 4;
    public const int CardsPerSuit = 13;
    private PlayingCard[,] cardPack;

    public Pack()
    {
        this.cardPack = new PlayingCard[NumSuits, CardsPerSuit];
        for (Suit suit = Suit.Clubs; suit <= Suit.Spades; suit++)
        {
            for (Value value = Value.Two; value <= Value.Ace; value++)
            {
                cardPack[(int)suit, (int)value] = new PlayingCard(suit, value);
            }
        }
    }
}

В этом случае Suit и Value являются перечислениями:

enum Suit { Clubs, Diamonds, Hearts, Spades }
enum Value { Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace}

и PlayingCard - это объект карты с определенным Suit и Value :

class PlayingCard
{
    private readonly Suit suit;
    private readonly Value value;

    public PlayingCard(Suit s, Value v)
    {
        this.suit = s;
        this.value = v;
    }
}



Простой и общий способ преобразования перечисления в нечто, с которым вы можете взаимодействовать:

public static Dictionary<int, string> ToList<T>() where T : struct
{
   return ((IEnumerable<T>)Enum
       .GetValues(typeof(T)))
       .ToDictionary(
           item => Convert.ToInt32(item),
           item => item.ToString());
}

А потом:

var enums = EnumHelper.ToList<MyEnum>();



Добавить метод public static IEnumerable<T> GetValues<T>() в ваш класс, например

public static IEnumerable<T> GetValues<T>()
{
    return Enum.GetValues(typeof(T)).Cast<T>();
}

вызовите и передайте свой enum, теперь вы можете перебирать его через foreach

 public static void EnumerateAllSuitsDemoMethod()
 {
     // custom method
     var foos = GetValues<Suit>(); 
     foreach (var foo in foos)
     {
         // Do something
     }
 }



Типы enum называются «перечисляемыми типами» не потому, что они являются контейнерами, которые «перечисляют» значения (которых они не являются), а потому, что они определяются путем перечисления возможных значений для переменной этого типа.

(На самом деле, это немного сложнее, чем типы перечислений, как считается, имеют «базовый» целочисленный тип, что означает, что каждое значение перечисления соответствует целочисленному значению (это обычно неявно, но может быть указано вручную). таким образом, чтобы вы могли набить любое целое число этого типа в переменную enum, даже если это не «именованное» значение.)

Метод System.Enum.GetNames может использоваться для извлечения массива строк, которые являются именами значений перечисления, как следует из названия.

EDIT: вместо этого предложил метод System.Enum.GetValues . К сожалению.




Related