枚举

 
所有枚举从 System.Enum(继承自 System.ValueType)继承。 适用于结构的所有规则也适用于枚举。
 
C# 程序使用 类型声明 创建新类型。 类型声明指定新类型的名称和成员。 用户可定义以下六种 C# 类型:类类型、结构类型、接口类型、枚举类型、委托类型和元组值类型。 还可以声明 record 类型( record struct 或
record class )。
记录类型具有编译器合成成员。 记录主要用于存储值,关联行为最少。
 
一.枚举类型
enum E {...} 格式的用户定义类型。 enum 类型是一种包含已命名常量的独特类型。 每个
enum 类型都有一个基础类型(必须是八种整型类型之一)。 enum 类型的值集与基础类型的值
集相同。

枚举类型定义了一组常数值。以下enum声明了定义不同根蔬菜的常数:

public enum SomeRootVegetable
{
HorseRadish,
Radish,
Turnip
}

 

还可以定义一个 enum 作为标志组合使用。 以下声明为四季声明了一组标志。 可以随意搭配季节组合,包括
All 值(包含所有季节):

public enum Seasons {
  None = 0,
  Summer = 1,
  Autumn = 2,
  Winter = 4,
  Spring = 8,
  All = Summer | Autumn | Winter | Spring
}

以下示例显示了前面两个枚举的声明:
var turnip = SomeRootVegetable.Turnip; 

var spring = Seasons.Spring;

var startingOnEquinox = Seasons.Spring | Seasons.Autumn;

var theYear = Seasons.All;
 
foreach 语句可用于枚举任何集合的元素。 以下代码从前一个示例中枚举数组:
 
foreach (int item in a) 
{
  Console.WriteLine(item);
}
可以使用 await foreach 语句来枚举序列:
await foreach (var number in GenerateSequence()) 
{
  Console.WriteLine(number);
}
枚举器的释放方式取决于 enumerator 类型的特征。 在常规同步情况下, finally 子句扩展为:
finally 
{
  (enumerator as IDisposable)?.Dispose();
}
常规异步情况扩展为:
finally 
{

if (enumerator is IAsyncDisposable asyncDisposable)

await asyncDisposable.DisposeAsync();
}
但是,如果 enumerator 的类型为已密封类型,并且不存在从类型 enumerator 到 IDisposable 或
IAsyncDisposable 的隐式转换,则 finally 子句扩展为一个空白块:
finally
{

}
如果存在从类型 enumerator 到 IDisposable 的隐式转换,并且 enumerator 是不可为 null 的值类型,则
finally 子句扩展为:
finally 
{ 
    ((IDisposable)enumerator).Dispose(); 
}
二.枚举约束
从 C# 7.3 开始,还可指定 System.Enum 类型作为基类约束。 CLR 始终允许此约束,但 C# 语言不允许。 使用
System.Enum 的泛型提供类型安全的编程,缓存使用 System.Enum 中静态方法的结果。 以下示例查找枚举类型
的所有有效的值,然后生成将这些值映射到其字符串表示形式的字典。
public static Dictionary<int, string> EnumNamedValues<T>() where T : System.Enum 
{
  var result = new Dictionary<int, string>();

  var values = Enum.GetValues(typeof(T));

  foreach (int item in values)
  result.Add(item, Enum.GetName(typeof(T), item));

  return result;
}
Enum.GetValues 和 Enum.GetName 使用反射,这会对性能产生影响。 可调用 EnumNamedValues 来生成可缓存和重
用的集合,而不是重复执行需要反射才能实施的调用。
如以下示例所示,可使用它来创建枚举并生成其值和名称的字典:
enum Rainbow 
{ Red, Orange, Yellow, Green, Blue, Indigo, Violet }

var map = EnumNamedValues<Rainbow>();

foreach (var pair in map)
Console.WriteLine($"{pair.Key}:\t{pair.Value}");
枚举类型 是由基础整型数值类型的一组命名常量定义的值类型。 若要定义枚举类型,请使用 enum 关键字并指
定枚举成员 的名称:
enum Season { Spring, Summer, Autumn, Winter }
默认情况下,枚举成员的关联常数值为类型 int ;它们从零开始,并按定义文本顺序递增 1。 可以显式指定任何
其他整数数值类型作为枚举类型的基础类型。 还可以显式指定关联的常数值,如下面的示例所示:
enum ErrorCode : ushort 
{
None = 0, Unknown = 1, ConnectionLost = 100, OutlierReading = 200
}
不能在枚举类型的定义内定义方法。 若要向枚举类型添加功能,请创建扩展方法。
枚举类型 E 的默认值是由表达式 (E)0 生成的值,即使零没有相应的枚举成员也是如此。
可以使用枚举类型,通过一组互斥值或选项组合来表示选项。 若要表示选项组合,请将枚举类型定义为位标志。
 
三.转换
对于任何枚举类型,枚举类型与其基础整型类型之间存在显式转换。 如果将枚举值转换为其基础类型,则结果为
枚举成员的关联整数值。
 
public enum Season { Spring, Summer, Autumn, Winter }

public class EnumConversionExample {

public static void Main()
{
Season a = Season.Autumn;
Console.WriteLine($"Integral value of {a} is {(int)a}");

// output: Integral value of Autumn is 2
var b = (Season)1;
Console.WriteLine(b);

// output: Summer
var c = (Season)4;
Console.WriteLine(c);
// output: 4
}
}
使用 Enum.IsDefined 方法来确定枚举类型是否包含具有特定关联值的枚举成员。
对于任何枚举类型,都存在分别与 System.Enum 类型的装箱和取消装箱相互转换。
 
四.枚举值和操作
每个枚举类型都定义了一个不同的类型;显式 枚举转换 () 需要在枚举类型和整型之间进行转换,或在两个枚举类
型之间进行转换。 枚举类型可以采用的值集不受其枚举成员限制。 特别是,枚举的基础类型的任何值都可以转
换为枚举类型,并且是该枚举类型的非重复有效值。
枚举成员具有其包含枚举类型的类型 (除了其他枚举成员初始值设定项中:请参阅 枚举成员) 。 使用关联值在枚
举类型中声明的枚举成员的值 E v 为 (E)v 。
可以在枚举类型的值上使用以下运算符: == 、 != 、、 < 、 > <= 、 >= (枚举比较运算符) 、binary + (加
法运算符) 、二进制 - (减法运算符) 、、 ( ^ & | 枚举逻辑运算符) 、 ( ~ 按位求补运算符) 以及 ++ ( --
后缀增量和减量运算符以及前缀增量和减量运算符) 。
每个枚举类型都自动派生自类 System.Enum (后者反过来派生自 System.ValueType 和 object ) 。 因此,此类的继
承方法和属性可用于枚举类型的值。
 
五.枚举逻辑举运算符
每个枚举类型都 E 隐式提供以下预定义的逻辑运算符:
E operator &(E x, E y); E operator |(E x, E y); E operator ^(E x, E y);
计算结果 x op y (其中 x 和 y 是具有基础类型的枚举类型的表达式 E U ), op 是一个逻辑运算符,与计
算完全相同 (E)((U)x op (U)y) 。 换言之,枚举类型逻辑运算符只对两个操作数的基础类型执行逻辑运算。
 
 
posted @ 2022-03-11 13:08  Tammytan  阅读(80)  评论(0编辑  收藏  举报