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()方法。
例如:下面示例定义了两个与颜色相关的枚举: SingleHue
和 MultiHue
。 后者具有 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
Parse
和 TryParse
方法允许将枚举值的字符串
表示形式转换为该值。字符串表示形式可以是枚举常量的名称
或基础值
。
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
类型不实现 IEnumerable
或 IEnumerable<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)