Класс System.Enum
В этой статье приводятся дополнительные замечания к справочной документации по этому API.
Перечисление — это набор именованных констант, базовый тип которого является любым целым типом. Если базовый тип явно не объявлен, Int32 используется. Enum — базовый класс для всех перечислений в .NET. Типы перечисления определяются enum
ключевое слово в C#, Enum
конструкцией ...End Enum
в Visual Basic и type
ключевое слово в F#.
Enum предоставляет методы для сравнения экземпляров этого класса, преобразования значения экземпляра в строковое представление, преобразования строкового представления числа в экземпляр этого класса и создания экземпляра указанного перечисления и значения.
Перечисление также можно рассматривать как битовое поле. Дополнительные сведения см. в разделе "Неисключающие члены" и раздел атрибута Flags и FlagsAttribute.
Создание типа перечисления
Языки программирования обычно предоставляют синтаксис для объявления перечисления, состоящего из набора именованных констант и их значений. В следующем примере показан синтаксис, используемый C#, F# и Visual Basic для определения перечисления. Он создает перечисление с тремя элементами ArrivalStatus
: ArrivalStatus.Early
, ArrivalStatus.OnTime
и ArrivalStatus.Late
. Обратите внимание, что во всех случаях перечисление не наследуется явным образом; связь наследования Enumобрабатывается неявно компилятором.
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
Предупреждение
Никогда не следует создавать тип перечисления, базовый тип которого не является целочисленным или Char. Хотя такой тип перечисления можно создать с помощью отражения, вызовы методов, использующие результирующий тип, являются ненадежными, а также могут вызывать дополнительные исключения.
Создание экземпляра типа перечисления
Вы можете создать экземпляр типа перечисления так же, как и создать экземпляр любого другого типа значения: объявив переменную и назначив одной из констант перечисления. В следующем примере создается ArrivalStatus
экземпляр, значение которого равно 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)
Вы также можете создать экземпляр значения перечисления следующими способами:
С помощью определенных функций языка программирования для приведения (как в C#) или преобразования (как в Visual Basic) целочисленного значения в значение перечисления. В следующем примере создается
ArrivalStatus
объект, значение которого находитсяArrivalStatus.Early
таким образом.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)
Вызывая неявный конструктор без параметров. Как показано в следующем примере, в этом случае базовое значение экземпляра перечисления равно 0. Однако это не обязательно значение допустимой константы в перечислении.
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)
Вызовите Parse или TryParse метод для синтаксического анализа строки, содержащей имя константы в перечислении. Дополнительные сведения см. в разделе "Анализ значений перечисления".
Вызывая ToObject метод для преобразования целочисленного значения в тип перечисления. Дополнительные сведения см. в разделе "Выполнение преобразований ".
Рекомендации по перечислению
Рекомендуется использовать следующие рекомендации при определении типов перечисления:
Если вы не определили элемент перечисления, значение которого равно 0, рассмотрите возможность создания
None
перечисленной константы. По умолчанию память, используемая для перечисления, инициализируется нулевой средой cl language runtime. Следовательно, если вы не определяете константу, значение которого равно нулю, перечисление будет содержать недопустимое значение при его создании.Если имеется очевидный вариант по умолчанию, который должен представлять приложение, рассмотрите возможность использования перечисленной константы, значение которой равно нулю для представления. Если по умолчанию нет регистра, попробуйте использовать перечислимую константу, значение которой равно нулю, чтобы указать регистр, который не представлен ни одной из других перечисленных констант.
Не указывайте перечисленные константы, зарезервированные для будущего использования.
При определении метода или свойства, принимающего перечисленную константу в качестве значения, рекомендуется проверять значение. Причина заключается в том, что можно привести числовое значение к типу перечисления, даже если это числовое значение не определено в перечислении.
Дополнительные рекомендации для типов перечисления, константы которых являются битовыми полями, перечислены в неисключающих элементах и разделе атрибута Flags.
Выполнение операций с перечислениями
При создании перечисления нельзя определить новые методы. Однако тип перечисления наследует полный набор статических и экземплярных методов из Enum класса. В следующих разделах рассматриваются большинство этих методов в дополнение к нескольким другим методам, которые часто используются при работе со значениями перечисления.
Выполнение преобразований
Можно преобразовать между элементом перечисления и его базовым типом с помощью приведения (в C# и F#) или оператора преобразования (в Visual Basic). В F# enum
функция также используется. В следующем примере операторы приведения или преобразования используются для преобразования как из целого числа в значение перечисления, так и из значения перечисления в целое число.
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)
Класс Enum также включает ToObject метод, который преобразует значение любого целочисленного типа в значение перечисления. В следующем примере метод используется ToObject(Type, Int32) для преобразования Int32ArrivalStatus
значения в значение. Обратите внимание, что, поскольку ToObject возвращает значение типа Object, использование оператора приведения или преобразования может по-прежнему потребоваться для приведения объекта к типу перечисления.
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)
При преобразовании целочисленного числа в значение перечисления можно назначить значение, которое на самом деле не является членом перечисления. Чтобы предотвратить это, перед выполнением преобразования можно передать целое число IsDefined методу. В следующем примере этот метод используется для определения возможности преобразования элементов в массив целочисленных значений в ArrivalStatus
значения.
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 Хотя класс предоставляет явные реализации IConvertible интерфейса для преобразования из значения перечисления в целочисленный тип, следует использовать методы Convert класса, напримерToInt32, для выполнения этих преобразований. В следующем примере показано, как использовать GetUnderlyingType метод вместе с Convert.ChangeType методом для преобразования значения перечисления в базовый тип. Обратите внимание, что в этом примере не требуется, чтобы базовый тип перечисления был известен во время компиляции.
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
Значения перечисления синтаксического анализа
TryParse Методы Parse позволяют преобразовать строковое представление значения перечисления в это значение. Строковое представление может быть либо именем, либо базовым значением константы перечисления. Обратите внимание, что методы синтаксического анализа успешно преобразуют строковые представления чисел, которые не являются членами определенного перечисления, если строки можно преобразовать в значение базового типа перечисления. Чтобы предотвратить это, метод можно вызвать, чтобы убедиться, IsDefined что результат метода синтаксического анализа является допустимым значением перечисления. В примере показан этот подход и демонстрируется вызовы как Parse(Type, String) методов, так и Enum.TryParse<TEnum>(String, TEnum) методов. Обратите внимание, что метод синтаксического анализа, отличный от универсального метода, возвращает объект, который может потребоваться привести (в C# и F#) или преобразовать (в Visual Basic) в соответствующий тип перечисления.
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
Формат значений перечисления
Значения перечисления можно преобразовать в их строковые представления, вызвав статический Format метод, а также перегрузки метода экземпляра ToString . Строку форматирования можно использовать для управления точным способом представления значения перечисления в виде строки. Дополнительные сведения см. в разделе "Строки формата перечисления". В следующем примере каждая из поддерживаемых строк формата перечисления ("G" или "g", "D" или "d", "X" или "x" и "F" или "f") используется для преобразования элемента ArrivalStatus
перечисления в его строковые представления.
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
Итерации элементов перечисления
Тип Enum не реализует IEnumerable или IEnumerable<T> интерфейс, который позволяет выполнять итерацию элементов коллекции с помощью foreach
конструкции (в C#), for..in
(в F#) или For Each
(в Visual Basic). Однако можно перечислить элементы двумя способами.
Метод можно вызвать GetNames для получения массива строк, содержащего имена элементов перечисления. Затем для каждого элемента массива строк можно вызвать Parse метод, чтобы преобразовать строку в эквивалентное значение перечисления. Этот подход показан в приведенном ниже примере.
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)
Метод можно вызвать GetValues для получения массива, содержащего базовые значения в перечислении. Затем для каждого элемента массива можно вызвать ToObject метод для преобразования целочисленного числа в его эквивалентное значение перечисления. Этот подход показан в приведенном ниже примере.
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)
Неисключающие члены и атрибут Flags
Одним из распространенных способов перечисления является представление набора взаимоисключающих значений. Например, ArrivalStatus
экземпляр может иметь значение Early
, OnTime
или Late
. Значение экземпляра ArrivalStatus
не имеет смысла отражать несколько констант перечисления.
Однако в других случаях значение объекта перечисления может включать несколько элементов перечисления, а каждый элемент представляет битовое поле в значении перечисления. Атрибут FlagsAttribute можно использовать для указания того, что перечисление состоит из битовых полей. Например, перечисление Pets
может использоваться для указания типов домашних животных в домашних хозяйствах. Его можно определить следующим образом.
[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
Затем перечисление Pets
можно использовать, как показано в следующем примере.
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)
При определении побитового перечисления и применении атрибута FlagsAttribute следует использовать следующие рекомендации.
FlagsAttribute Используйте настраиваемый атрибут для перечисления только в том случае, если выполняется побитовая операция (AND, OR, EXCLUSIVE OR) для числового значения.
Определите константы перечисления в полномочиях двух, то есть 1, 2, 4, 8 и т. д. Это означает, что отдельные флаги в объединенных констант перечислениях не перекрываются.
Рассмотрите возможность создания перечисленной константы для часто используемых сочетаний флагов. Например, если у вас есть перечисление, используемое для операций ввода-вывода файлов, содержащих перечисленные константы, и
Write = 2
рассмотрите возможность создания перечисленной константыRead = 1
ReadWrite = Read OR Write
, которая объединяетRead
иWrite
флаги. Кроме того, побитовая операция OR, используемая для объединения флагов, может рассматриваться как расширенная концепция в некоторых обстоятельствах, которые не должны требоваться для простых задач.Используйте осторожность, если вы определяете отрицательное число как перечисленную константу флага, так как многие позиции флагов могут иметь значение 1, что может заставить код запутать и поощрять ошибки программирования.
Удобный способ проверить, задан ли флаг в числовом значении, является вызов метода экземпляра HasFlag , как показано в следующем примере.
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.
Это эквивалентно выполнению побитовой операции AND между числовым значением и перечисленной константой флага, которая задает все биты в числовом значении нулю, которые не соответствуют флагу, а затем проверяет, равен ли результат этой операции перечисленной константе флага. Это продемонстрировано в следующем примере.
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.
Используйте
None
в качестве имени перечисленной константы флага, значение которой равно нулю. Вы не можете использоватьNone
перечисленную константу в побитовой операции AND для проверки флага, так как результат всегда равен нулю. Однако можно выполнить логическую, а не битовую, сравнение числовых значений иNone
перечисленной константы, чтобы определить, заданы ли биты в числовом значении. Это продемонстрировано в следующем примере.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.
Не определяйте значение перечисления исключительно для зеркало состоянии самого перечисления. Например, не определяйте перечислимую константу, которая просто помечает конец перечисления. Если необходимо определить последнее значение перечисления, проверка явно для этого значения. Кроме того, можно выполнить диапазон проверка для первой и последней перечисленной константы, если все значения в диапазоне допустимы.
Добавление методов перечисления
Так как типы перечисления определяются языковыми структурами, такими как enum
(C#) и Enum
(Visual Basic), нельзя определить настраиваемые методы для типа перечисления, отличного от этих методов, унаследованных от Enum класса. Однако можно использовать методы расширения для добавления функциональных возможностей в конкретный тип перечисления.
В следующем примере перечисление Grades
содержит возможные буквенные оценки, которые учащийся может получить в классе. Метод расширения с именем Passing
добавляется в тип Grades
, чтобы каждый экземпляр этого типа "знал", проходной это балл или нет. Класс Extensions
также содержит статическую переменную чтения и записи, которая определяет минимальный уровень прохождения. Возвращаемое значение Passing
метода расширения отражает текущее значение этой переменной.
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.
Примеры
В следующем примере показано использование перечисления для представления именованных значений и другого перечисления для представления именованных битовых полей.
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