什么是枚举

枚举是一个特殊的值类型,他可以让你指定一组命名的数值常量

  1. public enum
  2. BorderSide { Left,Right,Top,Bottom }
  3. BorderSide topSide =BorderSide.Top;
  4. bool isTop = (topSide==BorderSide.Top); //true

枚举的底层原理

每个枚举都对应一个底层的整形数值(Enum.GetUnderlyingType()).默认:是int类型
0,1,2..会按照枚举成员的声明顺序自动赋值
也可以指定其他的类型作为枚举的整数类型,例如byte:

  1. public enum BoderSide : byte { left,Right,Top,Bottom }

也可以单独指定枚举成员对应的整数值

  1. public enum BorderSide : byte { Left=1,Right=2,Top=10,Bottom=12 }

也可以只指定其中某些成员的数值,未被赋值的成员将接着它前面已赋值的成员的值进行递增

枚举的转换

枚举可以显式的和其底层的数值进行相互转换(和枚举代表的值)

  1. int i = (int)Border.Top;
  2. Border side = (Border)i;
  3. bool leftOrRight = (int)side <= 2;

0

在枚举表达式里面,0数值会被编译器特殊对待,它不需要显式的转换:

  1. BorderSide b = 0;
  2. if(b == 0) ...

因为枚举的第一个成员通常被当做“默认值”,它的值默认就是0
组合枚举里,0表示没有标志(flags)

FLAGS ENUM

可以对枚举的成员进行组合
为了避免歧义,枚举成员需要显示的赋值。典型的就是使用2的乘幂

  1. [Flags]
  2. public enum BorderSides { None=0,Left=1,Right=2,Top=4,Bottom=8 }

flags enum,可以使用位操作符,例如|和&

  1. [Flags] //(使用了Flags属性)
  2. public enum BorderSides
  3. {
  4. None = 0, Left = 1, Right = 2, Top = 4, Bottom = 8
  5. }
  6. BorderSides leftRight = BorderSides.Top | BorderSides.Right;
  7. if ((leftRight & BorderSides.Left) != 0)
  8. System.Console.WriteLine("Includes Left");
  9. string formatted = leftRight.ToString(); //使用[flags]"Left,Right",如果不使用[Flags]就是输出一个数值
  10. BorderSides s = BorderSides.Left;
  11. s |= BorderSides.Right;
  12. Console.WriteLine(s == leftRight); //True
  13. s ^= BorderSides.Right; //Roggles BorderSides.Right
  14. Console.WriteLine(s); // Left

FLAGS ENUM底层原理

未命名图片.png
未命名图片.png

FLAGS属性

按约定,如果枚举成员可组合的话,flags属性就应该应用在枚举类型上。
如果生命了这样的枚举却没有使用flags属性,你仍然可以组合枚举的成员,但是调用枚举实例的ToString()方法是,输出的是一个数值而不是一组名称。
按约定,可组合枚举的名称应该是复数的。 英文加上s
在声明可组合枚举的时候,可以直接使用组合的枚举成员作为成员:

  1. [Flags]
  2. public enum BorderSider
  3. {
  4. None=0,
  5. Left=1,Right=2,Top=4,Bottom=8,
  6. LeftRight = Left|Right,
  7. TopBottom = Top|Bottom,
  8. All = LeftRight|TopBottom
  9. }

枚举支持的操作符

未命名图片.png

类型安全的问题

  1. public enum BorderSide{ Left,Right,Top,Bottom }
  2. BorderSide b = (BorderSide) 12345;
  3. Console.WirteLine(b); //12345
  4. BorderSide b =BorderSide.Bottom;
  5. b++; //No errors

检查枚举值的合理性:Enum.IsDefined()静态方法。

  1. BorderSide side =(BorderSide)12345;
  2. Console.WriteLine(Enum.IsDefined(typeof(BorderSide),side));//false

如果是false就说明枚举值是不合理的。什么是嵌套类型
嵌套类型就是声明在另一个类型作用范围内的类型

  1. public class TopLevel
  2. {
  3. public class Nested{}
  4. public eunum Color{ Red,Blue,Tan}
  5. }

外面的类通常叫做里面那两个嵌套类型的封闭类型

嵌套类型的特性

可访问封闭类型的私有成员,以及任何封闭类型能访问的东西
可以使用所有访问修饰符来声明,不仅仅是public和internal
嵌套类型的默认访问级别是private而不是internal
从封闭类型外面访问嵌套类型需要使用到封闭类型的名称
未命名图片.png
image.png

嵌套类型的例子

未命名图片.png

思考题

  1. public enum BorderSide { Left,Right,Top,Bottom }

如何把上面这个枚举类型变成一个含有其所有成员/底层数值的集合?

  1. [BorderSide.Left,Border.Right,BorderSide.Top,BorderSide.Bottom]
  2. [0,1,2,3]