C# Enum 枚举

定义

是由一组底层是整数类型的命名常量定义的值类型
继承 :Object-- ValueType-- Enum

enum Season
{
    Spring,
    Summer,
    Autumn,
    Winter
}

默认情况下,枚举成员的关联常量值为 int 类型; 它们从零开始,并按照定义文本顺序增加一。 您可以显式指定任何其他整数数字类型作为枚举类型的基础类型。 您还可以显式指定关联的常量值,如以下示例所示:

enum ErrorCode : ushort
{
    None = 0,
    Unknown = 1,
    ConnectionLost = 100,
    OutlierReading = 200
}

C#枚举内部不能定义方法,要想给枚举添加方法,需要创建扩展方法

位标记枚举(bit flags)

一般枚举只能单项使用,如果您希望枚举类型表示选项的组合,请为枚举值设置为位字段,也就是说这些值都为2的幂。 然后,您可以使用按位逻辑运算符 | & 分别组合选项或交叉选项组合。
要定义这种枚举,首先为枚举加上FlagsAttribute属性,此属性的作用就是重写ToString()方法。
例如:下面示例定义了两个与颜色相关的枚举: SingleHueMultiHue 。 后者具有 FlagsAttribute 属性; 前者不具有属性。
3不能表示为 SingleHue 值,因为3不是 SingleHue任何成员的基础值 ,而 FlagsAttribute 特性使你可以将3 表示为 MultiHue 的值 Black, Red

using System;

class Example
{
   // Define an Enum without FlagsAttribute.
   enum SingleHue : short
   {
      None = 0,
      Black = 1,
      Red = 2,
      Green = 4,
      Blue = 8
   };

   // Define an Enum with FlagsAttribute.
   [Flags]
   enum MultiHue : short
   {
      None = 0,
      Black = 1,
      Red = 2,
      Green = 4,
      Blue = 8
   };

   static void Main( )
   {
      // Display all possible combinations of values.
      Console.WriteLine(
           "All possible combinations of values without FlagsAttribute:");
      for(int val = 0; val <= 16; val++ )
         Console.WriteLine( "{0,3} - {1:G}", val, (SingleHue)val);

      // Display all combinations of values, and invalid values.
      Console.WriteLine(
           "\nAll possible combinations of values with FlagsAttribute:");
      for( int val = 0; val <= 16; val++ )
         Console.WriteLine( "{0,3} - {1:G}", val, (MultiHue)val);
   }
}
// The example displays the following output:
//       All possible combinations of values without FlagsAttribute:
//         0 - None
//         1 - Black
//         2 - Red
//         3 - 3
//         4 - Green
//         5 - 5
//         6 - 6
//         7 - 7
//         8 - Blue
//         9 - 9
//        10 - 10
//        11 - 11
//        12 - 12
//        13 - 13
//        14 - 14
//        15 - 15
//        16 - 16
//
//       All possible combinations of values with FlagsAttribute:
//         0 - None
//         1 - Black
//         2 - Red
//         3 - Black, Red
//         4 - Green
//         5 - Black, Green
//         6 - Red, Green
//         7 - Black, Red, Green
//         8 - Blue
//         9 - Black, Blue
//        10 - Red, Blue
//        11 - Black, Red, Blue
//        12 - Green, Blue
//        13 - Black, Green, Blue
//        14 - Red, Green, Blue
//        15 - Black, Red, Green, Blue
//        16 - 16

下面的示例使用FlagsAttribute特性定义另一个枚举 ,并演示如何使用按位逻辑相等运算符来确定在枚举值中是否设置了一个或多个位域。

using System;

[Flags]
public enum PhoneService
{
   None = 0,
   LandLine = 1,
   Cell = 2,
   Fax = 4,
   Internet = 8,
   Other = 16
}

public class Example
{
   public static void Main()
   {
      // Define three variables representing the types of phone service
      // in three households.
      var household1 = PhoneService.LandLine | PhoneService.Cell |
                       PhoneService.Internet;
      var household2 = PhoneService.None;
      var household3 = PhoneService.Cell | PhoneService.Internet;

      // Store the variables in an array for ease of access.
      PhoneService[] households = { household1, household2, household3 };

      // Which households have no service?
      for (int ctr = 0; ctr < households.Length; ctr++)
         Console.WriteLine("Household {0} has phone service: {1}",
                           ctr + 1,
                           households[ctr] == PhoneService.None ?
                               "No" : "Yes");
      Console.WriteLine();

      // Which households have cell phone service?
      for (int ctr = 0; ctr < households.Length; ctr++)
         Console.WriteLine("Household {0} has cell phone service: {1}",
                           ctr + 1,
                           (households[ctr] & PhoneService.Cell) == PhoneService.Cell ?
                              "Yes" : "No");
      Console.WriteLine();

      // Which households have cell phones and land lines?
      var cellAndLand = PhoneService.Cell | PhoneService.LandLine;
      for (int ctr = 0; ctr < households.Length; ctr++)
         Console.WriteLine("Household {0} has cell and land line service: {1}",
                           ctr + 1,
                           (households[ctr] & cellAndLand) == cellAndLand ?
                              "Yes" : "No");
      Console.WriteLine();

      // List all types of service of each household?//
      for (int ctr = 0; ctr < households.Length; ctr++)
         Console.WriteLine("Household {0} has: {1:G}",
                           ctr + 1, households[ctr]);
      Console.WriteLine();
   }
}
// The example displays the following output:
//    Household 1 has phone service: Yes
//    Household 2 has phone service: No
//    Household 3 has phone service: Yes
//
//    Household 1 has cell phone service: Yes
//    Household 2 has cell phone service: No
//    Household 3 has cell phone service: Yes
//
//    Household 1 has cell and land line service: Yes
//    Household 2 has cell and land line service: No
//    Household 3 has cell and land line service: No
//
//    Household 1 has: LandLine, Cell, Internet
//    Household 2 has: None
//    Household 3 has: Cell, Internet

你还可以使用 Enum.HasFlag 方法来执行此操作。

using System;

[Flags] public enum DinnerItems {
   None = 0,
   Entree = 1,
   Appetizer = 2,
   Side = 4,
   Dessert = 8,
   Beverage = 16,
   BarBeverage = 32
}

public class Example
{
   public static void Main()
   {
      DinnerItems myOrder = DinnerItems.Appetizer | DinnerItems.Entree |
                            DinnerItems.Beverage | DinnerItems.Dessert;
      DinnerItems flagValue = DinnerItems.Entree | DinnerItems.Beverage;
      Console.WriteLine("{0} includes {1}: {2}",
                        myOrder, flagValue, myOrder.HasFlag(flagValue));
   }
}
// The example displays the following output:
//    Entree, Appetizer, Dessert, Beverage includes Entree, Beverage: True

利用枚举执行操作

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

执行转换

0可以隐式转换为枚举,枚举E的默认值也是E(0)

   public enum OperEnum
    {
        Add = 1,
        Update = 2
    }
//默认值为0
OperEnum v = default;
//隐式
OperEnum ves=0;
Console.WriteLine(ves==v);//true
//error,非0值需要强制转换
//OperEnum v1=1;
OperEnum v1=(OperEnum)1;

int value4=(int)v1;
//也可以采用下面这种方式
int number = -1;
ArrivalStatus arrived = (ArrivalStatus) ArrivalStatus.ToObject(typeof(ArrivalStatus), number);

在将整数转换为枚举值时,可以分配一个实际上不是枚举成员的值(例如OperEnum的0)。 若要防止出现这种情况,可以在执行转换之前将整数传递给 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);
      }
     // value为int或string都可以
     Enum.IsDefined(typeof(ArrivalStatus), "Late");//true
   }
}
// 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

ParseTryParse 方法允许将枚举值的字符串表示形式转换为该值。字符串表示形式可以是枚举常量的名称基础值

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

建议使用对应的泛型方法Parse<TEnum>(string value) TryParse<TEnum>(string? value, out TEnum result)

循环访问枚举成员

Enum 类型不实现 IEnumerableIEnumerable<T> 接口,所以不能直接遍历。

Enum提供GetNames方法和 GetValues方法,来遍历枚举的名称和值。

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)
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)
posted @ 2021-07-28 15:20  wangyfb  阅读(145)  评论(0编辑  收藏  举报