Поделиться через


Класс 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 = 1ReadWrite = 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