小窍门
开发软件的新手? 首先开始 学习入门 教程。 一旦你需要在代码中表示一组固定选项时,你将遇到枚举。
是否在其他语言中有经验? C# 枚举的工作方式与 Java 或 C++ 中的枚举类似,还支持位标志和模式匹配。 浏览 标志 和 switch 表达式 部分,以查找特定于 C# 的模式。
枚举类型(或枚举)定义一组由整数值支持的命名常量。 当值必须是固定选项集之一(星期几、HTTP 状态代码、日志级别或方向)时,请使用枚举。 枚举使代码比原始整数常量更具可读性和不易出错,因为编译器会确保使用命名值。
声明枚举
使用 enum 关键字后接类型名称及其成员,定义枚举:
enum Season
{
Spring,
Summer,
Autumn,
Winter
}
默认情况下,基础类型为 int,值以一个开头 0 并递增。
Season.Spring 是 0, Season.Summer 是 1,等等。
指定基础类型和显式值
可以选择不同的整型类型并分配显式值来控制数字表示形式:
enum HttpStatus : ushort
{
OK = 200,
NotFound = 404,
InternalServerError = 500
}
当数字具有外部含义(如 HTTP 状态代码或协议标识符)时,请使用显式值。 基础类型可以是任何整型类型,但char除外。 使用byte、short、ushort、int、uint或longulong。
在 switch 表达式中使用枚举
枚举可以自然地与 switch 表达式和模式匹配配合使用。 如果未处理所有成员,编译器会发出警告,这有助于防止在以后添加新值时出现 bug:
static string DescribeSeason(Season season) => season switch
{
Season.Spring => "Flowers bloom and temperatures rise.",
Season.Summer => "Long days and warm weather.",
Season.Autumn => "Leaves change color and fall.",
Season.Winter => "Short days and cold temperatures.",
_ => throw new ArgumentOutOfRangeException(nameof(season))
};
var today = Season.Autumn;
Console.WriteLine(DescribeSeason(today));
丢弃模式 (_) 处理未显式列出的任何值。
模式匹配 是一项 C# 功能,用于针对形状或条件测试值。 在此示例中,每个 case 用于检查枚举是否与特定成员匹配。 Switch 表达式是多种模式匹配形式之一。 有关模式匹配的详细信息,请参阅 模式匹配。
位标志
当枚举表示的是选项的组合而非单个选项时,请将每个成员定义为2的幂并应用FlagsAttribute:
[Flags]
enum FileAccess
{
None = 0,
Read = 1,
Write = 2,
Execute = 4,
ReadWrite = Read | Write,
All = Read | Write | Execute
}
通过使用 | 运算符合并值,并使用 HasFlag 测试各个标志:
var permissions = FileAccess.Read | FileAccess.Write;
Console.WriteLine(permissions); // ReadWrite
Console.WriteLine(permissions.HasFlag(FileAccess.Read)); // True
Console.WriteLine(permissions.HasFlag(FileAccess.Execute)); // False
该 [Flags] 属性还会影响 ToString()。 它以逗号分隔的名称(如 Read, Write)而不是原始数字的形式显示组合值。 有关详细信息,请参阅 System.FlagsAttribute。
在枚举和整数之间进行转换
显式转换用于在枚举和它的底层整数类型之间进行转换。
var status = HttpStatus.NotFound;
ushort code = (ushort)status;
Console.WriteLine($"Status: {status} ({code})"); // Status: NotFound (404)
var fromCode = (HttpStatus)200;
Console.WriteLine(fromCode); // OK
请注意,将整数转换为枚举不会验证该值是否与某个已定义的成员匹配。 使用 Enum.IsDefined 来检查从外部源接受的数字输入的有效性。
分析字符串并遍历值
基 Enum 类提供用于分析字符串和循环访问所有已定义值的方法:
// Parse a string to an enum value:
var parsed = Enum.Parse<Season>("Winter");
Console.WriteLine(parsed); // Winter
// Try to parse safely. It returns false only when the input can't be parsed. Call Enum.IsDefined to validate named members:
if (Enum.TryParse<Season>("Monsoon", out var unknown))
{
Console.WriteLine(unknown);
}
else
{
Console.WriteLine("'Monsoon' is not a valid Season"); // 'Monsoon' is not a valid Season
}
// Iterate over all values in an enum:
foreach (var season in Enum.GetValues<Season>())
{
Console.WriteLine($"{season} = {(int)season}");
}
// Spring = 0
// Summer = 1
// Autumn = 2
// Winter = 3
使用 Enum.TryParse<TEnum>(String, Boolean, TEnum) 代替 Enum.Parse<TEnum>(String) 当输入可能无效时。 它返回 false 而不是引发异常。