Enum 类

定义

为枚举提供基类。

public ref class Enum abstract : ValueType, IComparable, IConvertible, IFormattable
public ref class Enum abstract : ValueType, IComparable, IFormattable
public abstract class Enum : ValueType, IComparable, IConvertible, IFormattable
[System.Serializable]
public abstract class Enum : ValueType, IComparable, IConvertible, IFormattable
[System.Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public abstract class Enum : ValueType, IComparable, IConvertible, IFormattable
public abstract class Enum : ValueType, IComparable, IFormattable
type Enum = class
    inherit ValueType
    interface IComparable
    interface IConvertible
    interface IFormattable
[<System.Serializable>]
type Enum = class
    inherit ValueType
    interface IComparable
    interface IFormattable
    interface IConvertible
[<System.Serializable>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type Enum = class
    inherit ValueType
    interface IComparable
    interface IFormattable
    interface IConvertible
type Enum = class
    inherit ValueType
    interface IComparable
    interface IFormattable
Public MustInherit Class Enum
Inherits ValueType
Implements IComparable, IConvertible, IFormattable
Public MustInherit Class Enum
Inherits ValueType
Implements IComparable, IFormattable
继承
派生
属性
实现

示例

以下示例演示如何使用枚举来表示命名值,另一个枚举表示命名位字段。

using namespace System;
enum class Days
{
   Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday
};

enum class BoilingPoints
{
   Celsius = 100,
   Fahrenheit = 212
};

[Flags]

enum class Colors
{
   Red = 1,
   Green = 2,
   Blue = 4,
   Yellow = 8
};

int main()
{
   Type^ weekdays = Days::typeid;
   Type^ boiling = BoilingPoints::typeid;
   Console::WriteLine(  "The days of the week, and their corresponding values in the Days Enum are:" );
   Array^ a = Enum::GetNames( weekdays );
   Int32 i = 0;
   do
   {
      Object^ o = a->GetValue( i );
      Console::WriteLine(  "{0,-11}= {1}", o->ToString(), Enum::Format( weekdays, Enum::Parse( weekdays, o->ToString() ),  "d" ) );
   }
   while ( ++i < a->Length );

   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:" );
   i = 0;
   Array^ b = Enum::GetNames( boiling );
   do
   {
      Object^ o = b->GetValue( i );
      Console::WriteLine(  "{0,-11}= {1}", o->ToString(), Enum::Format( boiling, Enum::Parse( boiling, o->ToString() ),  "d" ) );
   }
   while ( ++i < b->Length );

   Array^ c = Enum::GetNames( Colors::typeid );
   Colors myColors = Colors::Red | Colors::Blue | Colors::Yellow;
   Console::WriteLine();
   Console::Write(  "myColors holds a combination of colors. Namely:" );
   for ( i = 0; i < 3; i++ )
      Console::Write(  " {0}", c->GetValue( i ) );
}
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

注解

枚举是一组命名常量,其基础类型是任何整型类型。 如果未显式声明基础类型, Int32 则使用。 Enum是.NET Framework中所有枚举的基类。 枚举类型由 enum C# 中的关键字、EnumVisual Basic 中的 ...End Enum 构造和 type F# 中的关键字定义。

Enum 提供用于比较此类实例的方法,将实例的值转换为其字符串表示形式,将数字的字符串表示形式转换为此类的实例,以及创建指定枚举和值的实例。

还可以将枚举视为位字段。 有关详细信息,请参阅 非独占成员和标志属性 部分和 FlagsAttribute 主题。

本主题内容:

创建枚举类型实例化枚举类型枚举最佳做法:使用枚举执行枚举执行操作,分析枚举值格式枚举值 ,循环访问枚举成员非独占成员 和 Flags 属性 添加枚举方法

创建枚举类型

编程语言通常提供语法来声明一个由一组命名常量及其值组成的枚举。 以下示例演示了 C#、F# 和Visual Basic用于定义枚举的语法。 它创建一 ArrivalStatus 个名为具有三个成员的枚举: ArrivalStatus.EarlyArrivalStatus.OnTime以及 ArrivalStatus.Late。 请注意,在所有情况下,枚举不会显式继承; Enum继承关系由编译器隐式处理。

public enum ArrivalStatus { Late=-1, OnTime=0, Early=1 };
type ArrivalStatus =
    | Late = -1
    | OnTime = 0
    | Early = 1
Public Enum ArrivalStatus As Integer
   Late = -1
   OnTime = 0
   Early = 1
End Enum

警告

不应创建基础类型为非整型的枚举类型或 Char。 尽管可以使用反射创建此类枚举类型,但使用生成的类型的方法调用是不可靠的,也可能引发其他异常。

实例化枚举类型

可以实例化枚举类型,就像实例化任何其他值类型一样:通过声明变量并向其分配枚举的常量之一。 以下示例实例化其值为 ArrivalStatus.OnTime a0/> 的实例ArrivalStatus化值。

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 Example
   Public Sub Main()
      Dim status As ArrivalStatus = ArrivalStatus.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 ArrivalStatus = CType(1, ArrivalStatus)
    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 ArrivalStatus()
    Console.WriteLine("Arrival Status: {0} ({0:D})", status1)
    ' The example displays the following output:
    '        Arrival Status: OnTime (0)
    
  • 通过调用 ParseTryParse 方法来分析包含枚举中常量名称的字符串。 有关详细信息,请参阅 “分析枚举值 ”部分。

  • 通过调用 ToObject 方法将整数值转换为枚举类型。 有关详细信息,请参阅 “执行转换” 部分。

枚举最佳做法

我们建议在定义枚举类型时使用以下最佳做法:

  • 如果尚未定义值为 0 的枚举成员,请考虑创建 None 枚举常量。 默认情况下,用于枚举的内存由公共语言运行时初始化为零。 因此,如果不定义值为零的常量,则创建枚举时将包含非法值。

  • 如果应用程序必须表示一个明显的默认情况,请考虑使用一个枚举常量,其值为零来表示它。 如果没有默认情况,请考虑使用值为零的枚举常量来指定其他任何枚举常量不表示的事例。

  • 不要指定为将来使用保留的枚举常量。

  • 定义将枚举常量作为值的方法或属性时,请考虑验证该值。 原因是,即使枚举中未定义该数值,也可以将数值强制转换为枚举类型。

有关常量是位字段的枚举类型的其他最佳做法,请参阅 “非独占成员”和“标志属性” 部分。

使用枚举执行操作

创建枚举时,无法定义新方法。 但是,枚举类型从 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 ArrivalStatus = CType(value3, ArrivalStatus)

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 ArrivalStatus = CType(ArrivalStatus.ToObject(GetType(ArrivalStatus), number), ArrivalStatus)

将整数转换为枚举值时,可以分配实际不是枚举成员的值。 若要防止这种情况,可以在执行转换之前将整数 IsDefined 传递给方法。 下面的示例使用此方法来确定整数值数组中的元素是否可以转换为 ArrivalStatus 值。

using System;

public enum ArrivalStatus { Unknown=-3, Late=-1, OnTime=0, Early=1 };

public class Example
{
   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 ArrivalStatus As Integer
   Unknown = -3
   Late = -1
   OnTime = 0
   Early = 1
End Enum

Module Example
   Public Sub Main()
      Dim values() As Integer = { -3, -1, 0, 1, 5, Int32.MaxValue }
      For Each value In values
         Dim status As ArrivalStatus
         If [Enum].IsDefined(GetType(ArrivalStatus), value)
            status = CType(value, ArrivalStatus) 
         Else
            status = ArrivalStatus.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 ArrivalStatus = ArrivalStatus.Early
Dim number = Convert.ChangeType(status, [Enum].GetUnderlyingType(GetType(ArrivalStatus)))
Console.WriteLine("Converted {0} to {1}", status, number)
' The example displays the following output:
'       Converted Early to 1

分析枚举值

使用 ParseTryParse 方法可以将枚举值的字符串表示形式转换为该值。 字符串表示形式可以是枚举常量的名称或基础值。 请注意,如果字符串可以转换为枚举的基础类型的值,则分析方法将成功转换不是特定枚举成员的数字的字符串表示形式。 为防止这种情况, 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 ArrivalStatus = CType([Enum].Parse(GetType(ArrivalStatus), number), ArrivalStatus)
   If Not [Enum].IsDefined(GetType(ArrivalStatus), status1) Then status1 = ArrivalStatus.Unknown
   Console.WriteLine("Converted '{0}' to {1}", number, status1)
Catch e As FormatException
   Console.WriteLine("Unable to convert '{0}' to an ArrivalStatus value.", 
                     number)
End Try   
   
Dim status2 As ArrivalStatus
If [Enum].TryParse(Of ArrivalStatus)(name, status2) Then
   If Not [Enum].IsDefined(GetType(ArrivalStatus), status2) Then status2 = ArrivalStatus.Unknown
   Console.WriteLine("Converted '{0}' to {1}", name, status2)
Else
   Console.WriteLine("Unable to convert '{0}' to an ArrivalStatus 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 ArrivalStatus = ArrivalStatus.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类型不实现IEnumerableIEnumerable<T>接口,这使你可以使用 C#) 中的 (、 for..in F#) 中的 (或For EachVisual Basic) 构造中的 (来循环访问集合foreach的成员。 但是,可以通过两种方式之一枚举成员。

  • 可以调用 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(ArrivalStatus))
    Console.WriteLine("Members of {0}:", GetType(ArrivalStatus).Name)
    Array.Sort(names)
    For Each name In names
       Dim status As ArrivalStatus = CType([Enum].Parse(GetType(ArrivalStatus), name),
                                     ArrivalStatus)
       Console.WriteLine("   {0} ({0:D})", status)
    Next
    ' The example displays the following output:
    '       Members of ArrivalStatus:
    '          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(ArrivalStatus))
    Console.WriteLine("Members of {0}:", GetType(ArrivalStatus).Name)
    For Each value In values
       Dim status As ArrivalStatus = CType([Enum].ToObject(GetType(ArrivalStatus), value),
                                           ArrivalStatus)
       Console.WriteLine("   {0} ({0:D})", status)
    Next                                       
    ' The example displays the following output:
    '       Members of ArrivalStatus:
    '          OnTime (0)
    '          Early (1)
    '          Unknown (-3)
    '          Late (-1)
    

非独占成员和 Flags 属性

枚举的一个常见用途是表示一组互斥值。 例如, ArrivalStatus 实例可以有一个值 EarlyOnTime或者 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 等)的枚举常量。 这意味着组合枚举常量中的单个标志不重叠。

  • 请考虑为常用标志组合创建枚举常量。 例如,如果你有用于包含枚举常量 Read = 1 的文件 I/O 操作的枚举,请考虑 Write = 2创建枚举常量 ReadWrite = Read OR Write,这将合并 ReadWrite 标志。 此外,在某些情况下,用于合并标志的按位 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 其值为零的标志枚举常量的名称。 不能在按位 AND 操作中使用 None 枚举常量来测试标志,因为结果始终为零。 但是,可以在数值与 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 Example
{
  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.

构造函数

Enum()

初始化 Enum 类的新实例。

方法

CompareTo(Object)

将此实例与指定对象进行比较并返回一个对二者的相对值的指示。

Equals(Object)

返回一个值,该值指示此实例是否等于指定的对象。

Format(Type, Object, String)

根据指定格式将指定枚举类型的指定值转换为其等效的字符串表示形式。

GetHashCode()

返回该实例的值的哈希代码。

GetName(Type, Object)

在指定枚举中检索具有指定值的常数的名称。

GetName<TEnum>(TEnum)

在指定枚举类型中检索具有指定值的常数的名称。

GetNames(Type)

检索指定枚举中常数名称的数组。

GetNames<TEnum>()

检索指定枚举类型中常数名称的数组。

GetType()

获取当前实例的 Type

(继承自 Object)
GetTypeCode()

返回此枚举成员的基础类型的类型代码。

GetUnderlyingType(Type)

返回指定枚举的基础类型。

GetValues(Type)

检索指定枚举中常数值的数组。

GetValues<TEnum>()

检索指定枚举类型中常数值的数组。

HasFlag(Enum)

确定当前实例中是否设置了一个或多个位域。

IsDefined(Type, Object)

返回一个布尔值,该值指示给定的整数值或其名称字符串是否存在于指定的枚举中。

IsDefined<TEnum>(TEnum)

返回一个布尔值,该值指示给定的整数值或其名称字符串是否存在于指定的枚举中。

MemberwiseClone()

创建当前 Object 的浅表副本。

(继承自 Object)
Parse(Type, ReadOnlySpan<Char>)

将一个或多个枚举常量的名称或数值的名称或数值的字符表示形式转换为等效的枚举对象。

Parse(Type, ReadOnlySpan<Char>, Boolean)

将一个或多个枚举常量的名称或数值的名称或数值的字符表示形式转换为等效的枚举对象。 一个参数指定该操作是否不区分大小写。

Parse(Type, String)

将一个或多个枚举常数的名称或数字值的字符串表示转换成等效的枚举对象。

Parse(Type, String, Boolean)

将一个或多个枚举常数的名称或数字值的字符串表示转换成等效的枚举对象。 一个参数指定该操作是否不区分大小写。

Parse<TEnum>(ReadOnlySpan<Char>)

将一个或多个枚举常量 TEnum 的名称或数值的字符表示形式转换为等效的枚举对象。

Parse<TEnum>(ReadOnlySpan<Char>, Boolean)

将一个或多个枚举常量 TEnum 的名称或数值的字符表示形式转换为等效的枚举对象。 一个参数指定该操作是否不区分大小写。

Parse<TEnum>(String)

TEnum 指定的一个或多个枚举常数的名称或数字值的字符串表示形式转换成等效的枚举对象。

Parse<TEnum>(String, Boolean)

TEnum 指定的一个或多个枚举常数的名称或数字值的字符串表示形式转换成等效的枚举对象。 一个参数指定该操作是否不区分大小写。

ToObject(Type, Byte)

将指定的 8 位无符号整数转换为枚举成员。

ToObject(Type, Int16)

将指定的 16 位有符号整数转换为枚举成员。

ToObject(Type, Int32)

将指定的 32 位有符号整数转换为枚举成员。

ToObject(Type, Int64)

将指定的 64 位有符号整数转换为枚举成员。

ToObject(Type, Object)

将具有整数值的指定对象转换为枚举成员。

ToObject(Type, SByte)

将指定的 8 位有符号整数值转换为枚举成员。

ToObject(Type, UInt16)

将指定的 16 位无符号整数值转换为枚举成员。

ToObject(Type, UInt32)

将指定的 32 位无符号整数值转换为枚举成员。

ToObject(Type, UInt64)

将指定的 64 位无符号整数值转换为枚举成员。

ToString()

将此实例的值转换为其等效的字符串表示形式。

ToString(IFormatProvider)
已过时。
已过时。

此方法重载已过时;请使用 ToString()

ToString(String)

使用指定格式将此实例的值转换成其等效的字符串表示。

ToString(String, IFormatProvider)
已过时。
已过时。

此方法重载已过时;请使用 ToString(String)

TryParse(Type, ReadOnlySpan<Char>, Boolean, Object)

将一个或多个枚举常量的名称或数值的名称或数值的字符表示形式转换为等效的枚举对象。 一个参数指定该操作是否不区分大小写。

TryParse(Type, ReadOnlySpan<Char>, Object)

将一个或多个枚举常量的名称或数值的名称或数值的字符表示形式转换为等效的枚举对象。

TryParse(Type, String, Boolean, Object)

将一个或多个枚举常数的名称或数字值的字符串表示转换成等效的枚举对象。

TryParse(Type, String, Object)

将一个或多个枚举常数的名称或数字值的字符串表示转换成等效的枚举对象。

TryParse<TEnum>(ReadOnlySpan<Char>, Boolean, TEnum)

将一个或多个枚举常数的名称或数字值的字符串表示转换成等效的枚举对象。 一个参数指定该操作是否区分大小写。 用于指示转换是否成功的返回值。

TryParse<TEnum>(ReadOnlySpan<Char>, TEnum)

将一个或多个枚举常数的名称或数字值的字符串表示转换成等效的枚举对象。

TryParse<TEnum>(String, Boolean, TEnum)

将一个或多个枚举常数的名称或数字值的字符串表示转换成等效的枚举对象。 一个参数指定该操作是否区分大小写。 用于指示转换是否成功的返回值。

TryParse<TEnum>(String, TEnum)

将一个或多个枚举常数的名称或数字值的字符串表示转换成等效的枚举对象。 用于指示转换是否成功的返回值。

显式接口实现

IConvertible.GetTypeCode()

返回此 Enum 实例的类型代码。

IConvertible.ToBoolean(IFormatProvider)

根据基础类型将当前值转换为布尔值。

IConvertible.ToByte(IFormatProvider)

根据基础类型将当前值转换为 8 位无符号整数。

IConvertible.ToChar(IFormatProvider)

根据基础类型将当前值转换为 Unicode 字符。

IConvertible.ToDateTime(IFormatProvider)

根据基础类型将当前值转换为 DateTime

IConvertible.ToDecimal(IFormatProvider)

根据基础类型将当前值转换为 Decimal

IConvertible.ToDouble(IFormatProvider)

根据基础类型将当前值转换为双精度浮点数。

IConvertible.ToInt16(IFormatProvider)

根据基础类型将当前值转换为 16 位有符号整数。

IConvertible.ToInt32(IFormatProvider)

根据基础类型将当前值转换为 32 位有符号整数。

IConvertible.ToInt64(IFormatProvider)

根据基础类型将当前值转换为 64 位有符号整数。

IConvertible.ToSByte(IFormatProvider)

根据基础类型将当前值转换为 8 位有符号整数。

IConvertible.ToSingle(IFormatProvider)

根据基础类型将当前值转换为单精度浮点数。

IConvertible.ToString(IFormatProvider)
已过时。

此方法重载已过时;请改用 ToString()

IConvertible.ToType(Type, IFormatProvider)

根据基础类型将当前值转换为指定类型。

IConvertible.ToUInt16(IFormatProvider)

根据基础类型将当前值转换为 16 位无符号整数。

IConvertible.ToUInt32(IFormatProvider)

根据基础类型将当前值转换为 32 位无符号整数。

IConvertible.ToUInt64(IFormatProvider)

根据基础类型将当前值转换为 64 位无符号整数。

IFormattable.ToString(String, IFormatProvider)
已过时。

此方法重载已过时;请使用 ToString(String)

适用于

线程安全性

此类型是线程安全的。

另请参阅