Общее количество элементов, определенных в перечислении

318

Как я могу получить количество элементов, определенных в перечислении?

SO User
источник

Ответы:

430

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

var myEnumMemberCount = Enum.GetNames(typeof(MyEnum)).Length;
Каспер Холдум
источник
1
Согласен ... вот ссылка, которую я нашел csharp411.com/c-count-items-in-an-enum
SO User
8
Можно также использовать Enum.GetValues.
Ксонатрон
6
System.Enum.GetNames, если вы еще не включили пространство имен System.
Бретт Пеннингс
4
Поэтому сегодня я снова столкнулся с этой проблемой. уловка стиля C, как описано в других ответах ниже, указана как проблематичная, но и Enum.GetValues, и Enum.GetNames, как указано выше, похоже, рискуют выделить целый новый массив только для получения фиксированной длины, которая кажется ... хорошо , какой ужас. Кто-нибудь знает, действительно ли такой подход требует динамического распределения? Если это так, то для определенных случаев использования это, безусловно, самое эффективное решение, если не самое гибкое.
J Trana
174

Вопрос в том:

Как я могу получить количество элементов, определенных в перечислении?

Количество «предметов» может означать две совершенно разные вещи. Рассмотрим следующий пример.

enum MyEnum
{
    A = 1,
    B = 2,
    C = 1,
    D = 3,
    E = 2
}

Какое количество "предметов" определено в MyEnum?

Количество предметов 5? ( A, B, C, D, E)

Или это 3? ( 1, 2, 3)

Количество имен, определенных в MyEnum(5), может быть вычислено следующим образом.

var namesCount = Enum.GetNames(typeof(MyEnum)).Length;

Число значений, определенных в MyEnum(3), может быть вычислено следующим образом.

var valuesCount = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().Distinct().Count();
Тимоти Шилдс
источник
2
Альтернативный способ написания последней строки var valuesCount = ((MyEnum[])Enum.GetValues(typeof(MyEnum))).Distinct().Count();.
Джеппе Стиг Нильсен
3
Я не могу вспомнить ни одного разработчика, которого я когда-либо встречал в своей жизни, который бы утверждал, что такое перечисление содержит 3 элемента.
motoDrizzt
2
@motoDrizzt вы можете найти что-то подобное в перечислении драйвера принтера, как Default = 1, A4 = 1, Portrate = 1, A4Portrait = 1, Landscape = 2, A4Landscape = 2, ...;).
ShA.t
72

Enum.GetValues (typeof (MyEnum)). Длина;

Мэтт Гамильтон
источник
7
Это быстрее использовать метод GetNames.
Каспер Холдум
Должны ли результаты кэшироваться в служебном классе?
djmj
14

Отличный трюк, который я видел в ответе C на этот вопрос, просто добавьте последний элемент в enum и используйте его, чтобы указать, сколько элементов в enum:

enum MyType {
  Type1,
  Type2,
  Type3,
  NumberOfTypes
}

В случае, когда вы определяете начальное значение, отличное от 0, вы можете использовать NumberOfTypes - Type1 для определения количества элементов.

Я не уверен, что этот метод будет быстрее, чем использование Enum, и я также не уверен, будет ли он рассматриваться как правильный способ сделать это, так как у нас есть Enum, чтобы выяснить эту информацию для нас.

мистифицировать
источник
1
это хорошо, так как я могу сделать это на XNA, потому что GetNames там недоступен
Тьяго Валле
Крутой трюк, это также будет быстрее, чем GetNames (), потому что он не должен считать их.
Джордан Лаприз
4
Остерегайтесь кода, который циклически перебирает перечисления через foreach - вы можете прочитать конец ваших массивов!
Майкл Дорган
4
Кроме того, остерегайтесь перечислений, которые определяют свои собственные значения - я часто использую перечисления для битовых флагов.
Мэтт Паркинс
1
Также остерегайтесь прямых привязок enum к некоторым элементам управления wpf, таким как combobox и
listbox
6

Из предыдущих ответов просто добавив пример кода.

 class Program
    {
        static void Main(string[] args)
        {
            int enumlen = Enum.GetNames(typeof(myenum)).Length;
            Console.Write(enumlen);
            Console.Read();
        }
        public enum myenum
        {
            value1,
            value2
        }
    }
jvanderh
источник
5

Вы можете использовать Enum.GetNames, чтобы возвратить IEnumerable значений в вашем перечислении, а затем .Count получить итоговый IEnumerable.

GetNames дает тот же результат, что и GetValues, но работает быстрее.

Лукас Уиллетт
источник
5

Если вы обнаружите, что пишете вышеупомянутое решение так же часто, как и я, вы можете реализовать его как универсальный:

public static int GetEnumEntries<T>() where T : struct, IConvertible 
{
    if (!typeof(T).IsEnum)
        throw new ArgumentException("T must be an enumerated type");

    return Enum.GetNames(typeof(T)).Length;
}
Мэтт Паркинс
источник
1

Я изучал это только сейчас и не был доволен удобочитаемостью текущего решения. Если вы пишете код неформально или в небольшом проекте, вы можете просто добавить еще один элемент в конец вашего перечисления под названием «Длина». Таким образом, вам нужно всего лишь набрать:

var namesCount = (int)MyEnum.Length;

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

EnergyWasRaw
источник
2
Это также зависит от enum, начинающегося с 0 (по умолчанию, но ни в коем случае не гарантируется). Кроме того, это делает intellisense для обычного использования enum очень запутанным. Это почти всегда ужасная идея.
BradleyDotNET
2
Это не заняло много времени :)
EnergyWasRaw
1
Интересно, я полагаю, вы никогда не знаете, когда может произойти что-то лучшее. Я приложил все усилия, чтобы избежать своего собственного решения, но нашел его достаточно интересным, чтобы поделиться им!
EnergyWasRaw
1

Для Visual Basic:

[Enum].GetNames(typeof(MyEnum)).Lengthне работал со мной, но [Enum].GetNames(GetType(Animal_Type)).lengthсделал.

S22
источник
Почему отрицательный голос? Это исправило мою проблему, это правильный синтаксис для VB, хотя вопрос помечен c #, все еще полезен.
М Гранья
2
Вероятно, это было связано с тем, что вопрос помечен C #, и в этом ответе не упоминалось, что он не использовал C #.
idbrii