Całkowita liczba pozycji zdefiniowanych w wyliczeniu

318

Jak mogę uzyskać liczbę elementów zdefiniowanych w wyliczeniu?

Użytkownik SO
źródło

Odpowiedzi:

430

Możesz użyć metody statycznej, Enum.GetNamesktóra zwraca tablicę reprezentującą nazwy wszystkich elementów w wyliczeniu. Właściwość length tej tablicy jest równa liczbie elementów zdefiniowanych w wyliczeniu

var myEnumMemberCount = Enum.GetNames(typeof(MyEnum)).Length;
Kasper Holdum
źródło
1
Zgadzam się ... oto link znalazłem csharp411.com/c-count-items-in-an-enum
SO Użytkownik
8
Można również użyć Enum.GetValues.
Xonatron,
6
System.Enum.GetNames, jeśli jeszcze nie uwzględniono przestrzeni nazw System.
Brett Pennings
4
Właśnie dzisiaj znów spotkałem się z tym problemem; sztuczka w stylu C opisana w innych odpowiedziach poniżej jest wymieniona jako problematyczna, ale zarówno Enum.GetValues, jak i Enum.GetNames wymienione powyżej wydają się ryzykować przydzielenie całej nowej tablicy tylko po to, aby uzyskać stałą długość, która wydaje się ... no cóż. , okropny. Czy ktoś wie, czy to podejście rzeczywiście pociąga za sobą dynamiczną alokację? Jeśli tak, w niektórych przypadkach użycia wydaje się to najbardziej wydajnym rozwiązaniem, jeśli nie najbardziej elastycznym.
J Trana,
174

Pytanie brzmi:

Jak mogę uzyskać liczbę elementów zdefiniowanych w wyliczeniu?

Liczba „przedmiotów” może naprawdę oznaczać dwie zupełnie różne rzeczy. Rozważ następujący przykład.

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

Jaka jest liczba „przedmiotów” zdefiniowanych w MyEnum?

Czy liczba pozycji wynosi 5? ( A, B, C, D, E)

Czy to jest 3? ( 1, 2, 3)

Liczbę nazw zdefiniowanych w MyEnum(5) można obliczyć w następujący sposób.

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

Liczbę wartości zdefiniowanych w MyEnum(3) można obliczyć w następujący sposób.

var valuesCount = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().Distinct().Count();
Tarcze Tymoteusza
źródło
2
Alternatywnym sposobem pisania ostatniej linii var valuesCount = ((MyEnum[])Enum.GetValues(typeof(MyEnum))).Distinct().Count();.
Jeppe Stig Nielsen
3
Nie mogę wymyślić żadnego programisty, którego spotkałem w życiu, który potwierdziłby, że taki wyliczenie zawiera 3 elementy.
motoDrizzt,
2
@motoDrizzt można znaleźć coś takiego w wyliczeniu sterownika drukarki, takiego jak Default = 1, A4 = 1, Portrate = 1, A4Portrait = 1, Landscape = 2, A4Landscape = 2, ...;).
shA.t
72

Enum.GetValues (typeof ( MyEnum )). Długość;

Matt Hamilton
źródło
7
Szybciej jest użyć metody GetNames.
Kasper Holdum
Czy wyniki powinny być buforowane w klasie użyteczności?
djmj
14

Sprytna sztuczka, którą widziałem w odpowiedzi C na to pytanie, po prostu dodaj ostatni element do wyliczenia i użyj go, aby powiedzieć, ile elementów jest w tym wyliczeniu:

enum MyType {
  Type1,
  Type2,
  Type3,
  NumberOfTypes
}

W przypadku, gdy definiujesz wartość początkową inną niż 0, możesz użyć NumberOfTypes - Type1, aby ustalić liczbę elementów.

Nie jestem pewien, czy ta metoda byłaby szybsza niż używanie Enum, a także nie jestem pewien, czy uznano by to za właściwy sposób, aby to zrobić, ponieważ mamy Enum do sprawdzenia dla nas tych informacji.

Josh
źródło
1
jest to miłe, ponieważ mogę to zrobić na XNA, ponieważ GetNames nie jest tam dostępne
Thiago Valle
Fajna sztuczka, byłoby to również szybsze niż GetNames (), ponieważ nie trzeba ich liczyć.
Jordan LaPrise
4
Uważaj na kod, który cyklicznie przechodzi przez wyliczenia przez foreach - możesz odczytać koniec swoich tablic!
Michael Dorgan
4
Uważaj też na wyliczenia, które definiują własne wartości - często używam wyliczeń do flag bitowych.
Matt Parkins
1
Uważaj również na bezpośrednie powiązania enum z niektórymi kontrolkami wpf, takimi jak combobox i listbox
mcy
6

Z poprzednich odpowiedzi po prostu dodałem przykładowy kod.

 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
źródło
5

Możesz użyć Enum.GetNames, aby zwrócić IEnumerable wartości w twoim enum, a następnie .Count wynikowy IEnumerable.

GetNames daje taki sam wynik jak GetValues, ale jest szybszy.

Lucas Willett
źródło
5

Jeśli zauważysz, że piszesz powyższe rozwiązanie tak często jak ja, możesz zaimplementować je jako ogólne:

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;
}
Matt Parkins
źródło
1

Właśnie się tym zajmowałem i nie byłem zadowolony z czytelności obecnego rozwiązania. Jeśli piszesz kod nieformalnie lub w małym projekcie, możesz po prostu dodać kolejny element na końcu wyliczenia o nazwie „Długość”. W ten sposób wystarczy wpisać:

var namesCount = (int)MyEnum.Length;

Oczywiście, jeśli inni zamierzają użyć twojego kodu - lub jestem pewien, że w wielu innych okolicznościach, które nie dotyczyły mnie w tym przypadku - to rozwiązanie może być gdziekolwiek, od złej porady po straszne.

EnergyWasRaw
źródło
2
Zależy to również od wyliczenia rozpoczynającego się od 0 (domyślnie, ale w żadnym wypadku nie jest gwarantowane). Dodatkowo sprawia, że ​​intellisense do normalnego używania enum jest bardzo mylące. To prawie zawsze okropny pomysł.
BradleyDotNET
2
Nie trwało to długo :)
EnergyWasRaw
1
Interesujące, przypuszczam, że nigdy nie wiadomo, kiedy może powstać coś lepszego. Zrobiłem co w mojej mocy, by odrzucić moje własne rozwiązanie, ale uznałem to za wystarczająco interesujące, aby się nim podzielić!
EnergyWasRaw
1

W przypadku Visual Basic:

[Enum].GetNames(typeof(MyEnum)).Lengthnie działało ze mną, ale działało [Enum].GetNames(GetType(Animal_Type)).length.

S22
źródło
Dlaczego głosowanie negatywne? To rozwiązało mój problem, jest to poprawna składnia dla VB, mimo że pytanie jest oznaczone jako c #, nadal przydatne.
M Granja,
2
Zanotowano prawdopodobnie dlatego, że pytanie jest oznaczone jako C #, a ta odpowiedź nie wspomniała, że ​​nie używa C #.
idbrii