Szukaj…
Wprowadzenie
Wyliczenie może pochodzić z dowolnego z następujących typów: bajt, sbyte, short, ushort, int, uint, long, ulong. Wartość domyślna to int i można ją zmienić, określając typ w definicji wyliczenia:
publiczne wyliczenie Dzień tygodnia: bajt {poniedziałek = 1, wtorek = 2, środa = 3, czwartek = 4, piątek = 5}
Jest to przydatne, gdy P / wywoływanie do kodu natywnego, mapowanie do źródeł danych i podobne okoliczności. Ogólnie rzecz biorąc, należy używać domyślnego int, ponieważ większość programistów oczekuje, że enum będzie int.
Składnia
- kolory enum {czerwony, zielony, niebieski} // deklaracja enum
- enum Kolory: bajt {czerwony, zielony, niebieski} // Deklaracja określonego typu
- enum Kolory {czerwony = 23, zielony = 45, niebieski = 12} // Deklaracja ze zdefiniowanymi wartościami
- Colors.Red // Uzyskaj dostęp do elementu Enum
- int value = (int) Colors.Red // Uzyskaj wartość int elementu wyliczeniowego
- Kolory color = (Colours) intValue // Uzyskaj element wyliczeniowy z int
Uwagi
Wyliczenie (skrót od „typ wyliczony”) to typ składający się z zestawu nazwanych stałych, reprezentowanych przez identyfikator specyficzny dla typu.
Wyliczenia są najbardziej przydatne do reprezentowania pojęć, które mają (zwykle małą) liczbę możliwych wartości dyskretnych. Na przykład można je wykorzystać do przedstawienia dnia tygodnia lub miesiąca w roku. Mogą być również używane jako flagi, które można łączyć lub sprawdzać za pomocą operacji bitowych.
Uzyskaj wszystkie wartości członków wyliczenia
enum MyEnum
{
One,
Two,
Three
}
foreach(MyEnum e in Enum.GetValues(typeof(MyEnum)))
Console.WriteLine(e);
Spowoduje to wydrukowanie:
One
Two
Three
Wylicz jako flagi
FlagsAttribute
można zastosować do wyliczenia, zmieniając zachowanie ToString()
celu dopasowania do charakteru wyliczenia:
[Flags]
enum MyEnum
{
//None = 0, can be used but not combined in bitwise operations
FlagA = 1,
FlagB = 2,
FlagC = 4,
FlagD = 8
//you must use powers of two or combinations of powers of two
//for bitwise operations to work
}
var twoFlags = MyEnum.FlagA | MyEnum.FlagB;
// This will enumerate all the flags in the variable: "FlagA, FlagB".
Console.WriteLine(twoFlags);
Ponieważ FlagsAttribute
opiera się na stałych wyliczenia, które są potęgami dwóch (lub ich kombinacji), a wartości wyliczeniowe są ostatecznie wartościami liczbowymi, jesteś ograniczony wielkością podstawowego typu liczbowego. Największym dostępnym typem numerycznym, którego można użyć, jest UInt64
, który pozwala określić 64 różne (niepołączone) stałe wyliczenia flagi. enum
kluczowe enum
domyślny typ int
, czyli Int32
. Kompilator pozwoli na deklarację wartości szerszych niż 32 bity. Będą one owijane bez ostrzeżenia i skutkują co najmniej dwoma członami wyliczenia o tej samej wartości. Dlatego jeśli wyliczenie ma pomieścić zestaw bitów składający się z więcej niż 32 flag, musisz jawnie określić większy typ:
public enum BigEnum : ulong
{
BigValue = 1 << 63
}
Chociaż flagi są często tylko jednym bitem, można je łączyć w nazwane „zestawy” dla łatwiejszego użycia.
[Flags]
enum FlagsEnum
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,
Default = Option1 | Option3,
All = Option1 | Option2 | Option3,
}
Aby uniknąć przeliterowania dziesiętnych wartości potęg dwóch, można również użyć operatora przesunięcia w lewo (<<) do zadeklarowania tego samego wyliczenia
[Flags]
enum FlagsEnum
{
None = 0,
Option1 = 1 << 0,
Option2 = 1 << 1,
Option3 = 1 << 2,
Default = Option1 | Option3,
All = Option1 | Option2 | Option3,
}
Począwszy od wersji C # 7.0 można również używać literałów binarnych .
Aby sprawdzić, czy wartość zmiennej wyliczeniowej ma określony zestaw flag, można HasFlag
metody HasFlag
. Powiedzmy, że mamy
[Flags]
enum MyEnum
{
One = 1,
Two = 2,
Three = 4
}
I value
var value = MyEnum.One | MyEnum.Two;
Za pomocą HasFlag
możemy sprawdzić, czy ustawiona jest jakakolwiek flaga
if(value.HasFlag(MyEnum.One))
Console.WriteLine("Enum has One");
if(value.HasFlag(MyEnum.Two))
Console.WriteLine("Enum has Two");
if(value.HasFlag(MyEnum.Three))
Console.WriteLine("Enum has Three");
Możemy również iterować wszystkie wartości wyliczenia, aby uzyskać wszystkie ustawione flagi
var type = typeof(MyEnum);
var names = Enum.GetNames(type);
foreach (var name in names)
{
var item = (MyEnum)Enum.Parse(type, name);
if (value.HasFlag(item))
Console.WriteLine("Enum has " + name);
}
Lub
foreach(MyEnum flagToCheck in Enum.GetValues(typeof(MyEnum)))
{
if(value.HasFlag(flagToCheck))
{
Console.WriteLine("Enum has " + flagToCheck);
}
}
Zostaną wydrukowane wszystkie trzy przykłady:
Enum has One
Enum has Two
Testuj wartości wyliczenia w stylu flagi za pomocą logiki bitowej
Wartość wyliczenia w stylu flagi należy przetestować przy użyciu logiki bitowej, ponieważ może ona nie być zgodna z żadną pojedynczą wartością.
[Flags]
enum FlagsEnum
{
Option1 = 1,
Option2 = 2,
Option3 = 4,
Option2And3 = Option2 | Option3;
Default = Option1 | Option3,
}
Wartość Default
jest w rzeczywistości kombinacją dwóch innych połączonych z bitowym OR. Dlatego, aby przetestować obecność flagi, musimy użyć bitowego AND.
var value = FlagsEnum.Default;
bool isOption2And3Set = (value & FlagsEnum.Option2And3) == FlagsEnum.Option2And3;
Assert.True(isOption2And3Set);
Enum do struny i z powrotem
public enum DayOfWeek
{
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
// Enum to string
string thursday = DayOfWeek.Thursday.ToString(); // "Thursday"
string seventhDay = Enum.GetName(typeof(DayOfWeek), 6); // "Saturday"
string monday = Enum.GetName(typeof(DayOfWeek), DayOfWeek.Monday); // "Monday"
// String to enum (.NET 4.0+ only - see below for alternative syntax for earlier .NET versions)
DayOfWeek tuesday;
Enum.TryParse("Tuesday", out tuesday); // DayOfWeek.Tuesday
DayOfWeek sunday;
bool matchFound1 = Enum.TryParse("SUNDAY", out sunday); // Returns false (case-sensitive match)
DayOfWeek wednesday;
bool matchFound2 = Enum.TryParse("WEDNESDAY", true, out wednesday); // Returns true; DayOfWeek.Wednesday (case-insensitive match)
// String to enum (all .NET versions)
DayOfWeek friday = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), "Friday"); // DayOfWeek.Friday
DayOfWeek caturday = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), "Caturady"); // Thows ArgumentException
// All names of an enum type as strings
string[] weekdays = Enum.GetNames(typeof(DayOfWeek));
Wartość domyślna dla wyliczenia == ZERO
Domyślna wartość wyliczenia wynosi zero . Jeśli wyliczenie nie definiuje elementu o wartości zero, jego domyślną wartością będzie zero.
public class Program
{
enum EnumExample
{
one = 1,
two = 2
}
public void Main()
{
var e = default(EnumExample);
if (e == EnumExample.one)
Console.WriteLine("defaults to one");
else
Console.WriteLine("Unknown");
}
}
Przykład: https://dotnetfiddle.net/l5Rwie
Podstawy wyliczania
Z MSDN :
Typ wyliczenia (zwany także wyliczeniem lub wyliczeniem) zapewnia skuteczny sposób zdefiniowania zestawu nazwanych stałych integralnych, które można przypisać do zmiennej .
Zasadniczo wyliczenie jest rodzajem, który pozwala tylko na zestaw skończonych opcji, a każda opcja odpowiada liczbie. Domyślnie liczby te rosną w kolejności deklaracji wartości, zaczynając od zera. Na przykład można zadeklarować wyliczenie dla dni tygodnia:
public enum Day
{
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
}
Tego wyliczenia można użyć w następujący sposób:
// Define variables with values corresponding to specific days
Day myFavoriteDay = Day.Friday;
Day myLeastFavoriteDay = Day.Monday;
// Get the int that corresponds to myFavoriteDay
// Friday is number 4
int myFavoriteDayIndex = (int)myFavoriteDay;
// Get the day that represents number 5
Day dayFive = (Day)5;
Domyślnie podstawowym typem każdego elementu w enum
jest int
, ale można również użyć byte
, sbyte
, short
, ushort
, uint
, long
i ulong
. Jeśli używasz typu innego niż int
, musisz określić typ za pomocą dwukropka po nazwie wyliczenia:
public enum Day : byte
{
// same as before
}
Liczby po nazwie są teraz bajtami zamiast liczb całkowitych. Możesz uzyskać podstawowy typ wyliczenia w następujący sposób:
Enum.GetUnderlyingType(typeof(Days)));
Wynik:
System.Byte
Demo: skrzypce .NET
Bitualna manipulacja za pomocą wyliczeń
FlagsAttribute należy stosować zawsze, gdy wyliczalny reprezentuje zbiór flag, a nie pojedynczą wartość. Wartość liczbowa przypisana do każdej wartości wyliczenia pomaga podczas manipulacji wyliczeniami za pomocą operatorów bitowych.
Przykład 1: z [flagami]
[Flags]
enum Colors
{
Red=1,
Blue=2,
Green=4,
Yellow=8
}
var color = Colors.Red | Colors.Blue;
Console.WriteLine(color.ToString());
drukuje czerwony, niebieski
Przykład 2: Bez [flag]
enum Colors
{
Red=1,
Blue=2,
Green=4,
Yellow=8
}
var color = Colors.Red | Colors.Blue;
Console.WriteLine(color.ToString());
wydruki 3
Użycie notacji << dla flag
Operatora przesunięcia w lewo ( <<
) można używać w deklaracjach wyliczania flag, aby zapewnić, że każda flaga ma dokładnie jedną 1
w reprezentacji binarnej, tak jak powinny.
Pomaga to również poprawić czytelność dużych wyliczeń z dużą ilością flag.
[Flags]
public enum MyEnum
{
None = 0,
Flag1 = 1 << 0,
Flag2 = 1 << 1,
Flag3 = 1 << 2,
Flag4 = 1 << 3,
Flag5 = 1 << 4,
...
Flag31 = 1 << 30
}
Oczywiste jest teraz, że MyEnum
zawiera tylko odpowiednie flagi, a nie żadne niechlujne rzeczy, takie jak Flag30 = 1073741822
(lub 111111111111111111111111111110 w formacie binarnym), co jest nieodpowiednie.
Dodanie dodatkowych informacji opisowych do wartości wyliczeniowej
W niektórych przypadkach możesz chcieć dodać dodatkowy opis do wartości wyliczenia, na przykład gdy sama wartość wyliczenia jest mniej czytelna niż to, co chciałbyś wyświetlić użytkownikowi. W takich przypadkach można użyć klasy System.ComponentModel.DescriptionAttribute
.
Na przykład:
public enum PossibleResults
{
[Description("Success")]
OK = 1,
[Description("File not found")]
FileNotFound = 2,
[Description("Access denied")]
AccessDenied = 3
}
Teraz, jeśli chcesz zwrócić opis określonej wartości wyliczenia, możesz wykonać następujące czynności:
public static string GetDescriptionAttribute(PossibleResults result)
{
return ((DescriptionAttribute)Attribute.GetCustomAttribute((result.GetType().GetField(result.ToString())), typeof(DescriptionAttribute))).Description;
}
static void Main(string[] args)
{
PossibleResults result = PossibleResults.FileNotFound;
Console.WriteLine(result); // Prints "FileNotFound"
Console.WriteLine(GetDescriptionAttribute(result)); // Prints "File not found"
}
Można to również łatwo przekształcić w metodę rozszerzenia dla wszystkich wyliczeń:
static class EnumExtensions
{
public static string GetDescription(this Enum enumValue)
{
return ((DescriptionAttribute)Attribute.GetCustomAttribute((enumValue.GetType().GetField(enumValue.ToString())), typeof(DescriptionAttribute))).Description;
}
}
A potem łatwo go używać w następujący sposób: Console.WriteLine(result.GetDescription());
Dodaj i usuń wartości z oznaczonego wyliczenia
Ten kod służy do dodawania i usuwania wartości z oznaczonego wystąpienia enum:
[Flags]
public enum MyEnum
{
Flag1 = 1 << 0,
Flag2 = 1 << 1,
Flag3 = 1 << 2
}
var value = MyEnum.Flag1;
// set additional value
value |= MyEnum.Flag2; //value is now Flag1, Flag2
value |= MyEnum.Flag3; //value is now Flag1, Flag2, Flag3
// remove flag
value &= ~MyEnum.Flag2; //value is now Flag1, Flag3
Wyliczenia mogą mieć nieoczekiwane wartości
Ponieważ wyliczenie można rzutować na i od jego bazowego typu całkowego, wartość może wykraczać poza zakres wartości podany w definicji typu wyliczeniowego.
Chociaż poniższy typ wyliczania DaysOfWeek
ma tylko 7 zdefiniowanych wartości, nadal może przechowywać dowolną wartość int
.
public enum DaysOfWeek
{
Monday = 1,
Tuesday = 2,
Wednesday = 3,
Thursday = 4,
Friday = 5,
Saturday = 6,
Sunday = 7
}
DaysOfWeek d = (DaysOfWeek)31;
Console.WriteLine(d); // prints 31
DaysOFWeek s = DaysOfWeek.Sunday;
s++; // No error
Obecnie nie ma możliwości zdefiniowania wyliczenia, które nie ma takiego zachowania.
Jednak niezdefiniowane wartości wyliczenia można wykryć za pomocą metody Enum.IsDefined
. Na przykład,
DaysOfWeek d = (DaysOfWeek)31;
Console.WriteLine(Enum.IsDefined(typeof(DaysOfWeek),d)); // prints False