System.Enum, klasa
Ten artykuł zawiera dodatkowe uwagi dotyczące dokumentacji referencyjnej dla tego interfejsu API.
Wyliczenie jest zestawem nazwanych stałych, których typ bazowy jest dowolnym typem całkowitym. Jeśli żaden typ bazowy nie jest jawnie zadeklarowany, Int32 jest używany. Enum jest klasą bazową dla wszystkich wyliczeń na platformie .NET. Typy wyliczenia są definiowane przez enum
słowo kluczowe w języku C#, konstrukcję Enum
...End Enum
w Visual Basic i type
słowo kluczowe w języku F#.
Enum Udostępnia metody porównywania wystąpień tej klasy, konwertowania wartości wystąpienia na reprezentację ciągu, konwertowanie reprezentacji ciągu liczby na wystąpienie tej klasy oraz tworzenie wystąpienia określonej wyliczenia i wartości.
Można również traktować wyliczenie jako pole bitowe. Aby uzyskać więcej informacji, zobacz sekcję Nie wykluczające się elementy członkowskie oraz sekcję atrybutu Flags i FlagsAttribute.
Tworzenie typu wyliczenia
Języki programowania zwykle zapewniają składnię do deklarowania wyliczenia składającego się z zestawu nazwanych stałych i ich wartości. Poniższy przykład ilustruje składnię używaną przez język C#, F# i Visual Basic do zdefiniowania wyliczenia. Tworzy wyliczenie o nazwie ArrivalStatus
zawierającej trzy elementy członkowskie: ArrivalStatus.Early
, ArrivalStatus.OnTime
i ArrivalStatus.Late
. Należy pamiętać, że we wszystkich przypadkach wyliczenie nie dziedziczy jawnie z Enum; relacja dziedziczenia jest obsługiwana niejawnie przez kompilator.
public enum ArrivalStatus { Unknown=-3, Late=-1, OnTime=0, Early=1 };
type ArrivalStatus =
| Late = -1
| OnTime = 0
| Early = 1
Public Enum ArrivalStatus1 As Integer
Late = -1
OnTime = 0
Early = 1
End Enum
Ostrzeżenie
Nigdy nie należy tworzyć typu wyliczenia, którego typ bazowy nie jest całkowity lub Char. Chociaż można utworzyć taki typ wyliczenia przy użyciu odbicia, wywołania metod używające wynikowego typu są zawodne i mogą również zgłaszać dodatkowe wyjątki.
Tworzenie wystąpienia typu wyliczenia
Możesz utworzyć wystąpienie typu wyliczenia tak samo, jak wystąpienie dowolnego innego typu wartości: deklarując zmienną i przypisując do niej jedną z stałych wyliczenia. Poniższy przykład tworzy wystąpienie, ArrivalStatus
którego wartość to ArrivalStatus.OnTime
.
public class Example
{
public static void Main()
{
ArrivalStatus status = ArrivalStatus.OnTime;
Console.WriteLine("Arrival Status: {0} ({0:D})", status);
}
}
// The example displays the following output:
// Arrival Status: OnTime (0)
let status = ArrivalStatus.OnTime
printfn $"Arrival Status: {status} ({status:D})"
// The example displays the following output:
// Arrival Status: OnTime (0)
Public Module Example1
Public Sub Main()
Dim status As ArrivalStatus1 = ArrivalStatus1.OnTime
Console.WriteLine("Arrival Status: {0} ({0:D})", status)
End Sub
End Module
' The example displays the following output:
' Arrival Status: OnTime (0)
Możesz również utworzyć wystąpienie wartości wyliczenia w następujący sposób:
Używając funkcji określonego języka programowania do rzutowania (tak jak w języku C#) lub konwertowania (jak w Visual Basic) wartości całkowitej na wartość wyliczenia. Poniższy przykład tworzy
ArrivalStatus
obiekt, którego wartość jestArrivalStatus.Early
w ten sposób.ArrivalStatus status2 = (ArrivalStatus)1; Console.WriteLine("Arrival Status: {0} ({0:D})", status2); // The example displays the following output: // Arrival Status: Early (1)
let status2 = enum<ArrivalStatus> 1 printfn $"Arrival Status: {status2} ({status2:D})" // The example displays the following output: // Arrival Status: Early (1)
Dim status2 As ArrivalStatus2 = CType(1, ArrivalStatus2) Console.WriteLine("Arrival Status: {0} ({0:D})", status2) ' The example displays the following output: ' Arrival Status: Early (1)
Wywołując niejawny konstruktor bez parametrów. Jak pokazano w poniższym przykładzie, w tym przypadku podstawowa wartość wystąpienia wyliczenia wynosi 0. Jednak niekoniecznie jest to wartość prawidłowej stałej w wyliczenie.
ArrivalStatus status1 = new ArrivalStatus(); Console.WriteLine("Arrival Status: {0} ({0:D})", status1); // The example displays the following output: // Arrival Status: OnTime (0)
let status1 = ArrivalStatus() printfn $"Arrival Status: {status1} ({status1:D})" // The example displays the following output: // Arrival Status: OnTime (0)
Dim status1 As New ArrivalStatus2() Console.WriteLine("Arrival Status: {0} ({0:D})", status1) ' The example displays the following output: ' Arrival Status: OnTime (0)
Wywołując metodę Parse or TryParse , aby przeanalizować ciąg zawierający nazwę stałej w wyliczenie. Aby uzyskać więcej informacji, zobacz sekcję Analizowanie wartości wyliczenia.
Wywołując metodę ToObject w celu przekonwertowania wartości całkowitej na typ wyliczenia. Aby uzyskać więcej informacji, zobacz sekcję Wykonywanie konwersji .
Najlepsze rozwiązania dotyczące wyliczania
Zalecamy użycie następujących najlepszych rozwiązań podczas definiowania typów wyliczenia:
Jeśli nie zdefiniowano elementu członkowskiego wyliczenia, którego wartość wynosi 0, rozważ utworzenie stałej
None
wyliczanej. Domyślnie pamięć używana do wyliczania jest inicjowana do zera przez środowisko uruchomieniowe języka wspólnego. W związku z tym jeśli nie zdefiniujesz stałej, której wartość jest równa zero, wyliczenie będzie zawierać niedozwoloną wartość podczas jej tworzenia.Jeśli istnieje oczywisty przypadek domyślny, który aplikacja musi reprezentować, rozważ użycie wyliczonej stałej, której wartość jest równa zero, aby ją reprezentować. Jeśli nie ma przypadku domyślnego, rozważ użycie stałej wyliczonej, której wartość to zero, aby określić przypadek, który nie jest reprezentowany przez żadną z pozostałych wyliczonych stałych.
Nie należy określać wyliczonych stałych zarezerwowanych do użytku w przyszłości.
Podczas definiowania metody lub właściwości, która przyjmuje wyliczonej stałej jako wartość, rozważ zweryfikowanie wartości. Przyczyną jest możliwość rzutowania wartości liczbowej na typ wyliczenia, nawet jeśli ta wartość liczbowa nie jest zdefiniowana w wyliczeniem.
Dodatkowe najlepsze rozwiązania dotyczące typów wyliczenia, których stałe są polami bitowymi, są wymienione w sekcji Elementy członkowskie bez wykluczania i Atrybut Flags.
Wykonywanie operacji przy użyciu wyliczeń
Podczas tworzenia wyliczenia nie można definiować nowych metod. Jednak typ wyliczenia dziedziczy pełny zestaw metod statycznych i wystąpień z Enum klasy . W poniższych sekcjach przedstawiono większość tych metod, oprócz kilku innych metod, które są często używane podczas pracy z wartościami wyliczenia.
Wykonywanie konwersji
Można przekonwertować między elementem członkowskim wyliczenia i jego typem bazowym przy użyciu operatora rzutowania (w języku C# i F#) lub konwersji (w Visual Basic). W języku enum
F#funkcja jest również używana. W poniższym przykładzie użyto operatorów rzutowania lub konwersji, aby wykonać konwersje zarówno z liczby całkowitej, jak i z wartości wyliczenia do liczby całkowitej.
int value3 = 2;
ArrivalStatus status3 = (ArrivalStatus)value3;
int value4 = (int)status3;
let value3 = 2
let status3 = enum<ArrivalStatus> value3
let value4 = int status3
Dim value3 As Integer = 2
Dim status3 As ArrivalStatus2 = CType(value3, ArrivalStatus2)
Dim value4 As Integer = CInt(status3)
Klasa Enum zawiera również metodę ToObject , która konwertuje wartość dowolnego typu całkowitego na wartość wyliczenia. W poniższym przykładzie użyto ToObject(Type, Int32) metody , aby przekonwertować Int32 element na ArrivalStatus
wartość. Należy pamiętać, że ponieważ ToObject zwraca wartość typu Object, użycie operatora rzutowania lub konwersji może być nadal konieczne, aby rzutować obiekt na typ wyliczenia.
int number = -1;
ArrivalStatus arrived = (ArrivalStatus)ArrivalStatus.ToObject(typeof(ArrivalStatus), number);
let number = -1
let arrived = ArrivalStatus.ToObject(typeof<ArrivalStatus>, number) :?> ArrivalStatus
Dim number As Integer = -1
Dim arrived As ArrivalStatus2 = CType(ArrivalStatus2.ToObject(GetType(ArrivalStatus2), number), ArrivalStatus2)
Podczas konwertowania liczby całkowitej na wartość wyliczenia można przypisać wartość, która nie jest elementem członkowskim wyliczenia. Aby temu zapobiec, można przekazać liczbę całkowitą do IsDefined metody przed wykonaniem konwersji. W poniższym przykładzie użyto tej metody, aby określić, czy elementy w tablicy wartości całkowitych można przekonwertować na ArrivalStatus
wartości.
using System;
public class Example3
{
public static void Main()
{
int[] values = { -3, -1, 0, 1, 5, Int32.MaxValue };
foreach (var value in values)
{
ArrivalStatus status;
if (Enum.IsDefined(typeof(ArrivalStatus), value))
status = (ArrivalStatus)value;
else
status = ArrivalStatus.Unknown;
Console.WriteLine("Converted {0:N0} to {1}", value, status);
}
}
}
// The example displays the following output:
// Converted -3 to Unknown
// Converted -1 to Late
// Converted 0 to OnTime
// Converted 1 to Early
// Converted 5 to Unknown
// Converted 2,147,483,647 to Unknown
open System
type ArrivalStatus =
| Unknown = -3
| Late = -1
| OnTime = 0
| Early = 1
let values = [ -3; -1; 0; 1; 5; Int32.MaxValue ]
for value in values do
let status =
if Enum.IsDefined(typeof<ArrivalStatus>, value) then
enum value
else
ArrivalStatus.Unknown
printfn $"Converted {value:N0} to {status}"
// The example displays the following output:
// Converted -3 to Unknown
// Converted -1 to Late
// Converted 0 to OnTime
// Converted 1 to Early
// Converted 5 to Unknown
// Converted 2,147,483,647 to Unknown
Public Enum ArrivalStatus4 As Integer
Unknown = -3
Late = -1
OnTime = 0
Early = 1
End Enum
Module Example4
Public Sub Main()
Dim values() As Integer = {-3, -1, 0, 1, 5, Int32.MaxValue}
For Each value In values
Dim status As ArrivalStatus4
If [Enum].IsDefined(GetType(ArrivalStatus4), value) Then
status = CType(value, ArrivalStatus4)
Else
status = ArrivalStatus4.Unknown
End If
Console.WriteLine("Converted {0:N0} to {1}", value, status)
Next
End Sub
End Module
' The example displays the following output:
' Converted -3 to Unknown
' Converted -1 to Late
' Converted 0 to OnTime
' Converted 1 to Early
' Converted 5 to Unknown
' Converted 2,147,483,647 to Unknown
Enum Mimo że klasa udostępnia jawne implementacje interfejsu interfejsu IConvertible do konwertowania z wartości wyliczenia na typ całkowity, należy użyć metod Convert klasy, takich jak ToInt32, aby wykonać te konwersje. W poniższym przykładzie pokazano, jak można użyć GetUnderlyingType metody wraz z Convert.ChangeType metodą w celu przekonwertowania wartości wyliczenia na jej typ bazowy. Należy pamiętać, że ten przykład nie wymaga, aby podstawowy typ wyliczenia był znany w czasie kompilacji.
ArrivalStatus status = ArrivalStatus.Early;
var number = Convert.ChangeType(status, Enum.GetUnderlyingType(typeof(ArrivalStatus)));
Console.WriteLine("Converted {0} to {1}", status, number);
// The example displays the following output:
// Converted Early to 1
let status = ArrivalStatus.Early
let number = Convert.ChangeType(status, Enum.GetUnderlyingType typeof<ArrivalStatus>)
printfn $"Converted {status} to {number}"
// The example displays the following output:
// Converted Early to 1
Dim status As ArrivalStatus5 = ArrivalStatus5.Early
Dim number = Convert.ChangeType(status, [Enum].GetUnderlyingType(GetType(ArrivalStatus5)))
Console.WriteLine("Converted {0} to {1}", status, number)
' The example displays the following output:
' Converted Early to 1
Analizowanie wartości wyliczenia
Metody Parse i TryParse umożliwiają konwertowanie ciągu reprezentacji wartości wyliczenia na wartość. Reprezentacja ciągu może być nazwą lub podstawową wartością stałej wyliczenia. Należy pamiętać, że metody analizowania zostaną pomyślnie przekonwertowane reprezentacje ciągów liczb, które nie są elementami członkowskimi określonego wyliczenia, jeśli ciągi można przekonwertować na wartość typu bazowego wyliczenia. Aby temu zapobiec, można wywołać metodę w celu upewnienia się, IsDefined że wynik metody analizy jest prawidłową wartością wyliczenia. W przykładzie pokazano to podejście i pokazano wywołania metod Parse(Type, String) i .Enum.TryParse<TEnum>(String, TEnum) Należy pamiętać, że metoda analizowania innego niż ogólna zwraca obiekt, który może być konieczne rzutowanie (w języku C# i F#) lub przekonwertowanie (w Visual Basic) na odpowiedni typ wyliczenia.
string number = "-1";
string name = "Early";
try
{
ArrivalStatus status1 = (ArrivalStatus)Enum.Parse(typeof(ArrivalStatus), number);
if (!(Enum.IsDefined(typeof(ArrivalStatus), status1)))
status1 = ArrivalStatus.Unknown;
Console.WriteLine("Converted '{0}' to {1}", number, status1);
}
catch (FormatException)
{
Console.WriteLine("Unable to convert '{0}' to an ArrivalStatus value.",
number);
}
ArrivalStatus status2;
if (Enum.TryParse<ArrivalStatus>(name, out status2))
{
if (!(Enum.IsDefined(typeof(ArrivalStatus), status2)))
status2 = ArrivalStatus.Unknown;
Console.WriteLine("Converted '{0}' to {1}", name, status2);
}
else
{
Console.WriteLine("Unable to convert '{0}' to an ArrivalStatus value.",
number);
}
// The example displays the following output:
// Converted '-1' to Late
// Converted 'Early' to Early
let number = "-1"
let name = "Early"
try
let status1 = Enum.Parse(typeof<ArrivalStatus>, number) :?> ArrivalStatus
let status1 =
if not (Enum.IsDefined(typeof<ArrivalStatus>, status1) ) then
ArrivalStatus.Unknown
else
status1
printfn $"Converted '{number}' to {status1}"
with :? FormatException ->
printfn $"Unable to convert '{number}' to an ArrivalStatus value."
match Enum.TryParse<ArrivalStatus> name with
| true, status2 ->
let status2 =
if not (Enum.IsDefined(typeof<ArrivalStatus>, status2) ) then
ArrivalStatus.Unknown
else
status2
printfn $"Converted '{name}' to {status2}"
| _ ->
printfn $"Unable to convert '{number}' to an ArrivalStatus value."
// The example displays the following output:
// Converted '-1' to Late
// Converted 'Early' to Early
Dim number As String = "-1"
Dim name As String = "Early"
Dim invalid As String = "32"
Try
Dim status1 As ArrivalStatus8 = CType([Enum].Parse(GetType(ArrivalStatus8), number), ArrivalStatus8)
If Not [Enum].IsDefined(GetType(ArrivalStatus8), status1) Then status1 = ArrivalStatus8.Unknown
Console.WriteLine("Converted '{0}' to {1}", number, status1)
Catch e As FormatException
Console.WriteLine("Unable to convert '{0}' to an ArrivalStatus8 value.",
number)
End Try
Dim status2 As ArrivalStatus8
If [Enum].TryParse(Of ArrivalStatus8)(name, status2) Then
If Not [Enum].IsDefined(GetType(ArrivalStatus8), status2) Then status2 = ArrivalStatus8.Unknown
Console.WriteLine("Converted '{0}' to {1}", name, status2)
Else
Console.WriteLine("Unable to convert '{0}' to an ArrivalStatus8 value.",
number)
End If
' The example displays the following output:
' Converted '-1' to Late
' Converted 'Early' to Early
Formatuj wartości wyliczenia
Wartości wyliczenia można przekonwertować na ich reprezentacje ciągów, wywołując metodę statyczną Format , a także przeciążenia metody wystąpienia ToString . Możesz użyć ciągu formatu, aby kontrolować dokładny sposób, w jaki wartość wyliczenia jest reprezentowana jako ciąg. Aby uzyskać więcej informacji, zobacz Ciągi formatu wyliczenia. W poniższym przykładzie użyto każdego z obsługiwanych ciągów formatu wyliczenia ("G" lub "g", "D" lub "d", "X" lub "x" oraz "F" lub "f" ) w celu przekonwertowania elementu członkowskiego ArrivalStatus
wyliczenia na jego reprezentacje ciągów.
string[] formats = { "G", "F", "D", "X" };
ArrivalStatus status = ArrivalStatus.Late;
foreach (var fmt in formats)
Console.WriteLine(status.ToString(fmt));
// The example displays the following output:
// Late
// Late
// -1
// FFFFFFFF
let formats = [ "G"; "F"; "D"; "X" ]
let status = ArrivalStatus.Late
for fmt in formats do
printfn $"{status.ToString fmt}"
// The example displays the following output:
// Late
// Late
// -1
// FFFFFFFF
Dim formats() As String = {"G", "F", "D", "X"}
Dim status As ArrivalStatus6 = ArrivalStatus6.Late
For Each fmt As String In formats
Console.WriteLine(status.ToString(fmt))
Next
' The example displays the following output:
' Late
' Late
' -1
' FFFFFFFF
Iterowanie elementów członkowskich wyliczania
Typ Enum nie implementuje interfejsu IEnumerable lub IEnumerable<T> , który umożliwia iterowanie elementów członkowskich kolekcji przy użyciu foreach
konstrukcji (w języku C#), for..in
(w języku F#) ani For Each
(w Visual Basic). Można jednak wyliczyć elementy członkowskie na jeden z dwóch sposobów.
Metodę GetNames można wywołać, aby pobrać tablicę ciągów zawierającą nazwy elementów członkowskich wyliczenia. Następnie dla każdego elementu tablicy ciągów można wywołać metodę Parse , aby przekonwertować ciąg na równoważną wartość wyliczenia. To podejście pokazano w poniższym przykładzie.
string[] names = Enum.GetNames(typeof(ArrivalStatus)); Console.WriteLine("Members of {0}:", typeof(ArrivalStatus).Name); Array.Sort(names); foreach (var name in names) { ArrivalStatus status = (ArrivalStatus)Enum.Parse(typeof(ArrivalStatus), name); Console.WriteLine(" {0} ({0:D})", status); } // The example displays the following output: // Members of ArrivalStatus: // Early (1) // Late (-1) // OnTime (0) // Unknown (-3)
let names = Enum.GetNames typeof<ArrivalStatus> printfn $"Members of {nameof ArrivalStatus}:" let names = Array.sort names for name in names do let status = Enum.Parse(typeof<ArrivalStatus>, name) :?> ArrivalStatus printfn $" {status} ({status:D})" // The example displays the following output: // Members of ArrivalStatus: // Early (1) // Late (-1) // OnTime (0) // Unknown (-3)
Dim names() As String = [Enum].GetNames(GetType(ArrivalStatus7)) Console.WriteLine("Members of {0}:", GetType(ArrivalStatus7).Name) Array.Sort(names) For Each name In names Dim status As ArrivalStatus7 = CType([Enum].Parse(GetType(ArrivalStatus7), name), ArrivalStatus7) Console.WriteLine(" {0} ({0:D})", status) Next ' The example displays the following output: ' Members of ArrivalStatus7: ' Early (1) ' Late (-1) ' OnTime (0) ' Unknown (-3)
Metodę GetValues można wywołać, aby pobrać tablicę zawierającą wartości bazowe w wyliczenie. Następnie dla każdego elementu tablicy można wywołać metodę ToObject , aby przekonwertować liczbę całkowitą na równoważną wartość wyliczenia. To podejście pokazano w poniższym przykładzie.
var values = Enum.GetValues(typeof(ArrivalStatus)); Console.WriteLine("Members of {0}:", typeof(ArrivalStatus).Name); foreach (ArrivalStatus status in values) { Console.WriteLine(" {0} ({0:D})", status); } // The example displays the following output: // Members of ArrivalStatus: // OnTime (0) // Early (1) // Unknown (-3) // Late (-1)
let values = Enum.GetValues typeof<ArrivalStatus> printfn $"Members of {nameof ArrivalStatus}:" for status in values do printfn $" {status} ({status:D})" // The example displays the following output: // Members of ArrivalStatus: // OnTime (0) // Early (1) // Unknown (-3) // Late (-1)
Dim values = [Enum].GetValues(GetType(ArrivalStatus7)) Console.WriteLine("Members of {0}:", GetType(ArrivalStatus7).Name) For Each value In values Dim status As ArrivalStatus7 = CType([Enum].ToObject(GetType(ArrivalStatus7), value), ArrivalStatus7) Console.WriteLine(" {0} ({0:D})", status) Next ' The example displays the following output: ' Members of ArrivalStatus7: ' OnTime (0) ' Early (1) ' Unknown (-3) ' Late (-1)
Nie wykluczające się elementy członkowskie i atrybut Flags
Jednym z typowych zastosowań wyliczenia jest reprezentowanie zestawu wzajemnie wykluczających się wartości. Na przykład ArrivalStatus
wystąpienie może mieć wartość Early
, OnTime
lub Late
. Nie ma sensu, aby wartość ArrivalStatus
wystąpienia odzwierciedlała więcej niż jedną stałą wyliczenia.
W innych przypadkach jednak wartość obiektu wyliczenia może zawierać wiele elementów członkowskich wyliczenia, a każdy element członkowski reprezentuje pole bitowe w wartości wyliczenia. Atrybut FlagsAttribute może służyć do wskazania, że wyliczenie składa się z pól bitowych. Na przykład wyliczenie o nazwie Pets
może służyć do wskazywania rodzajów zwierząt domowych w gospodarstwie domowym. Można go zdefiniować w następujący sposób.
[Flags]
public enum Pets
{
None = 0, Dog = 1, Cat = 2, Bird = 4, Rodent = 8,
Reptile = 16, Other = 32
};
[<Flags>]
type Pets =
| None = 0
| Dog = 1
| Cat = 2
| Bird = 4
| Rodent = 8
| Reptile = 16
| Other = 32
<Flags> Public Enum Pets As Integer
None = 0
Dog = 1
Cat = 2
Bird = 4
Rodent = 8
Reptile = 16
Other = 32
End Enum
Następnie Pets
można użyć wyliczenia, jak pokazano w poniższym przykładzie.
Pets familyPets = Pets.Dog | Pets.Cat;
Console.WriteLine("Pets: {0:G} ({0:D})", familyPets);
// The example displays the following output:
// Pets: Dog, Cat (3)
let familyPets = Pets.Dog ||| Pets.Cat
printfn $"Pets: {familyPets:G} ({familyPets:D})"
// The example displays the following output:
// Pets: Dog, Cat (3)
Dim familyPets As Pets = Pets.Dog Or Pets.Cat
Console.WriteLine("Pets: {0:G} ({0:D})", familyPets)
' The example displays the following output:
' Pets: Dog, Cat (3)
Podczas definiowania wyliczenia bitowego i stosowania atrybutu FlagsAttribute należy użyć następujących najlepszych rozwiązań.
Użyj atrybutu niestandardowego FlagsAttribute dla wyliczenia tylko wtedy, gdy operacja bitowa (AND, OR, EXCLUSIVE OR) ma być wykonywana na wartości liczbowej.
Zdefiniuj stałe wyliczenia w uprawnieniach dwóch, czyli 1, 2, 4, 8 itd. Oznacza to, że poszczególne flagi w połączonych stałych wyliczenia nie nakładają się na siebie.
Rozważ utworzenie stałej wyliczonej dla powszechnie używanych kombinacji flag. Jeśli na przykład masz wyliczenie używane dla operacji we/wy plików, które zawierają wyliczone stałe
Read = 1
iWrite = 2
, rozważ utworzenie wyliczonej stałejReadWrite = Read OR Write
, która łączyRead
flagi iWrite
. Ponadto bitowa operacja OR używana do łączenia flag może być uznawana za zaawansowaną koncepcję w pewnych okolicznościach, które nie powinny być wymagane w przypadku prostych zadań.Zachowaj ostrożność, jeśli zdefiniujesz liczbę ujemną jako stałą wyliczeniową flagę, ponieważ wiele pozycji flag może być ustawionych na 1, co może spowodować, że kod będzie mylący i zachęca do błędów kodowania.
Wygodnym sposobem sprawdzenia, czy flaga jest ustawiona w wartości liczbowej, jest wywołanie metody wystąpienia HasFlag , jak pokazano w poniższym przykładzie.
Pets familyPets = Pets.Dog | Pets.Cat; if (familyPets.HasFlag(Pets.Dog)) Console.WriteLine("The family has a dog."); // The example displays the following output: // The family has a dog.
let familyPets = Pets.Dog ||| Pets.Cat if familyPets.HasFlag Pets.Dog then printfn "The family has a dog." // The example displays the following output: // The family has a dog.
Dim familyPets As Pets = Pets.Dog Or Pets.Cat If familyPets.HasFlag(Pets.Dog) Then Console.WriteLine("The family has a dog.") End If ' The example displays the following output: ' The family has a dog.
Jest to odpowiednik wykonywania bitowej operacji AND między wartością liczbową a wyliczeniową stałą flagą, która ustawia wszystkie bity w wartości liczbowej na zero, które nie odpowiadają flagi, a następnie testuje, czy wynik tej operacji jest równy stałej wyliczonej flagi. Przedstawiono to w poniższym przykładzie.
Pets familyPets = Pets.Dog | Pets.Cat; if ((familyPets & Pets.Dog) == Pets.Dog) Console.WriteLine("The family has a dog."); // The example displays the following output: // The family has a dog.
let familyPets = Pets.Dog ||| Pets.Cat if (familyPets &&& Pets.Dog) = Pets.Dog then printfn "The family has a dog." // The example displays the following output: // The family has a dog.
Dim familyPets As Pets = Pets.Dog Or Pets.Cat If familyPets And Pets.Dog = Pets.Dog Then Console.WriteLine("The family has a dog.") End If ' The example displays the following output: ' The family has a dog.
Użyj
None
jako nazwy flagi wyliczonej stałej, której wartość to zero. Nie można użyć wyliczonej stałejNone
w bitowej operacji AND, aby przetestować flagę, ponieważ wynik jest zawsze zerowy. Można jednak wykonać logiczne, a nie bitowe porównanie wartości liczbowej i wyliczonej stałejNone
, aby określić, czy są ustawione jakiekolwiek bity w wartości liczbowej. Przedstawiono to w poniższym przykładzie.Pets familyPets = Pets.Dog | Pets.Cat; if (familyPets == Pets.None) Console.WriteLine("The family has no pets."); else Console.WriteLine("The family has pets."); // The example displays the following output: // The family has pets.
let familyPets = Pets.Dog ||| Pets.Cat if familyPets = Pets.None then printfn "The family has no pets." else printfn "The family has pets." // The example displays the following output: // The family has pets.
Dim familyPets As Pets = Pets.Dog Or Pets.Cat If familyPets = Pets.None Then Console.WriteLine("The family has no pets.") Else Console.WriteLine("The family has pets.") End If ' The example displays the following output: ' The family has pets.
Nie należy definiować wartości wyliczenia wyłącznie w celu zdublowania stanu samego wyliczenia. Na przykład nie należy definiować wyliczonej stałej, która jedynie oznacza koniec wyliczenia. Jeśli musisz określić ostatnią wartość wyliczenia, sprawdź jawnie, czy ta wartość jest jawna. Ponadto można wykonać sprawdzanie zakresu dla pierwszej i ostatniej wyliczonej stałej, jeśli wszystkie wartości w zakresie są prawidłowe.
Dodawanie metod wyliczania
Ponieważ typy wyliczenia są definiowane przez struktury języków, takie jak enum
(C#) i Enum
(Visual Basic), nie można zdefiniować metod niestandardowych dla typu wyliczenia innego niż te metody dziedziczone z Enum klasy. Można jednak użyć metod rozszerzeń, aby dodać funkcjonalność do określonego typu wyliczenia.
W poniższym przykładzie Grades
wyliczenie reprezentuje możliwe oceny listów, które student może otrzymać w klasie. Metoda rozszerzenia o nazwie Passing
jest dodawana do Grades
typu, aby każde wystąpienie tego typu teraz "wie", czy reprezentuje klasę przekazującą, czy nie. Klasa Extensions
zawiera również statyczną zmienną odczytu i zapisu, która definiuje minimalną klasę przekazywania. Wartość Passing
zwracana metody rozszerzenia odzwierciedla bieżącą wartość tej zmiennej.
using System;
// Define an enumeration to represent student grades.
public enum Grades { F = 0, D = 1, C = 2, B = 3, A = 4 };
// Define an extension method for the Grades enumeration.
public static class Extensions
{
public static Grades minPassing = Grades.D;
public static bool Passing(this Grades grade)
{
return grade >= minPassing;
}
}
class Example8
{
static void Main()
{
Grades g1 = Grades.D;
Grades g2 = Grades.F;
Console.WriteLine("{0} {1} a passing grade.", g1, g1.Passing() ? "is" : "is not");
Console.WriteLine("{0} {1} a passing grade.", g2, g2.Passing() ? "is" : "is not");
Extensions.minPassing = Grades.C;
Console.WriteLine("\nRaising the bar!\n");
Console.WriteLine("{0} {1} a passing grade.", g1, g1.Passing() ? "is" : "is not");
Console.WriteLine("{0} {1} a passing grade.", g2, g2.Passing() ? "is" : "is not");
}
}
// The exmaple displays the following output:
// D is a passing grade.
// F is not a passing grade.
//
// Raising the bar!
//
// D is not a passing grade.
// F is not a passing grade.
open System
open System.Runtime.CompilerServices
// Define an enumeration to represent student grades.
type Grades =
| F = 0
| D = 1
| C = 2
| B = 3
| A = 4
let mutable minPassing = Grades.D
// Define an extension method for the Grades enumeration.
[<Extension>]
type Extensions =
[<Extension>]
static member Passing(grade) = grade >= minPassing
let g1 = Grades.D
let g2 = Grades.F
printfn $"""{g1} {if g1.Passing() then "is" else "is not"} a passing grade."""
printfn $"""{g2} {if g2.Passing() then "is" else "is not"} a passing grade."""
minPassing <- Grades.C
printfn "\nRaising the bar!\n"
printfn $"""{g1} {if g1.Passing() then "is" else "is not"} a passing grade."""
printfn $"""{g2} {if g2.Passing() then "is" else "is not"} a passing grade."""
// The exmaple displays the following output:
// D is a passing grade.
// F is not a passing grade.
//
// Raising the bar!
//
// D is not a passing grade.
// F is not a passing grade.
Imports System.Runtime.CompilerServices
' Define an enumeration to represent student grades.
Public Enum Grades As Integer
F = 0
D = 1
C = 2
B = 3
A = 4
End Enum
' Define an extension method for the Grades enumeration.
Public Module Extensions
Public minPassing As Grades = Grades.D
<Extension>
Public Function Passing(grade As Grades) As Boolean
Return grade >= minPassing
End Function
End Module
Public Module Example
Public Sub Main()
Dim g1 As Grades = Grades.D
Dim g2 As Grades = Grades.F
Console.WriteLine("{0} {1} a passing grade.",
g1, If(g1.Passing(), "is", "is not"))
Console.WriteLine("{0} {1} a passing grade.",
g2, If(g2.Passing(), "is", "is not"))
Console.WriteLine()
Extensions.minPassing = Grades.C
Console.WriteLine("Raising the bar!")
Console.WriteLine()
Console.WriteLine("{0} {1} a passing grade.",
g1, If(g1.Passing(), "is", "is not"))
Console.WriteLine("{0} {1} a passing grade.",
g2, If(g2.Passing(), "is", "is not"))
End Sub
End Module
' The exmaple displays the following output:
' D is a passing grade.
' F is not a passing grade.
'
' Raising the bar!
'
' D is not a passing grade.
' F is not a passing grade.
Przykłady
W poniższym przykładzie pokazano użycie wyliczenia do reprezentowania nazwanych wartości i innego wyliczenia reprezentującego nazwane pola bitowe.
using System;
public class EnumTest {
enum Days { Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday };
enum BoilingPoints { Celsius = 100, Fahrenheit = 212 };
[Flags]
enum Colors { Red = 1, Green = 2, Blue = 4, Yellow = 8 };
public static void Main() {
Type weekdays = typeof(Days);
Type boiling = typeof(BoilingPoints);
Console.WriteLine("The days of the week, and their corresponding values in the Days Enum are:");
foreach ( string s in Enum.GetNames(weekdays) )
Console.WriteLine( "{0,-11}= {1}", s, Enum.Format( weekdays, Enum.Parse(weekdays, s), "d"));
Console.WriteLine();
Console.WriteLine("Enums can also be created which have values that represent some meaningful amount.");
Console.WriteLine("The BoilingPoints Enum defines the following items, and corresponding values:");
foreach ( string s in Enum.GetNames(boiling) )
Console.WriteLine( "{0,-11}= {1}", s, Enum.Format(boiling, Enum.Parse(boiling, s), "d"));
Colors myColors = Colors.Red | Colors.Blue | Colors.Yellow;
Console.WriteLine();
Console.WriteLine("myColors holds a combination of colors. Namely: {0}", myColors);
}
}
open System
type Days =
| Saturday = 0
| Sunday = 1
| Monday = 2
| Tuesday = 3
| Wednesday = 4
| Thursday = 5
| Friday = 6
type BoilingPoints =
| Celsius = 100
| Fahrenheit = 212
[<Flags>]
type Colors =
| Red = 1
| Green = 2
| Blue = 4
| Yellow = 8
let weekdays = typeof<Days>
let boiling = typeof<BoilingPoints>
printfn "The days of the week, and their corresponding values in the Days Enum are:"
for s in Enum.GetNames weekdays do
printfn $"""{s,-11}= {Enum.Format(weekdays, Enum.Parse(weekdays, s), "d")}"""
printfn "\nEnums can also be created which have values that represent some meaningful amount."
printfn "The BoilingPoints Enum defines the following items, and corresponding values:"
for s in Enum.GetNames boiling do
printfn $"""{s,-11}= {Enum.Format(boiling, Enum.Parse(boiling, s), "d")}"""
let myColors = Colors.Red ||| Colors.Blue ||| Colors.Yellow
printfn $"\nmyColors holds a combination of colors. Namely: {myColors}"
Public Class EnumTest
Enum Days
Saturday
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
End Enum
Enum BoilingPoints
Celsius = 100
Fahrenheit = 212
End Enum
<Flags()> _
Enum Colors
Red = 1
Green = 2
Blue = 4
Yellow = 8
End Enum
Public Shared Sub Main()
Dim weekdays As Type = GetType(Days)
Dim boiling As Type = GetType(BoilingPoints)
Console.WriteLine("The days of the week, and their corresponding values in the Days Enum are:")
Dim s As String
For Each s In [Enum].GetNames(weekdays)
Console.WriteLine("{0,-11} = {1}", s, [Enum].Format(weekdays, [Enum].Parse(weekdays, s), "d"))
Next s
Console.WriteLine()
Console.WriteLine("Enums can also be created which have values that represent some meaningful amount.")
Console.WriteLine("The BoilingPoints Enum defines the following items, and corresponding values:")
For Each s In [Enum].GetNames(boiling)
Console.WriteLine("{0,-11} = {1}", s, [Enum].Format(boiling, [Enum].Parse(boiling, s), "d"))
Next s
Dim myColors As Colors = Colors.Red Or Colors.Blue Or Colors.Yellow
Console.WriteLine()
Console.WriteLine("myColors holds a combination of colors. Namely: {0}", myColors)
End Sub
End Class