枚举类型一般情况下多作为描述性质的参数,我们可以组合不同的属性到枚举之中,而且可以很容易地从枚举对象中读取出是否包含指定的参数(开关)。
枚举参数的好处是可以将多个选项值存放到一个变量之中,减少存储空间。
因为在.NET中,一个布尔值(Boolean)就占用4字节,而一个四字节的Integer可以存储高达32个选项开关!

那么如何定义一个枚举参数呢?这里只有一个最简单的定律,那就是乘2。
比如基础参数为1,那么第二个参数就是2,第三个就是4,之后以此类推即可。
这种方法采用的是二进制的位移原理,只要乘2便可定位到下一个开关位置。
你也可以直接使用位移操作符<<来设置参数的数值,下面有演示代码。

一个枚举模型
<Flags()> _
Enum flags
    none = 0
    f1 = 1 << 0 '1
    f2 = 1 << 1 '2
    f3 = 1 << 2 '4
    f4 = 1 << 3 '8
    f5 = 1 << 4 '16
    f6 = 1 << 5 '32
    f7 = 1 << 6 '64
    f8 = 1 << 7 '128
End Enum
检测方法也很简单,我们可以在 VB 中使用 Or 来将开关组合到一起,判断时将参数与你的预期数值进行 And 合取,返回的数值如果等于预期值,那么便表示所有的参数都一致!

判断是否包含指定的参数(开关)
Dim f As flags = flags.f1 Or flags.f8

'.NET 4.0 之前需要自己写检测方法
Shared Function checkFlag(ByVal value As Integer, ByVal flags As Integer) As Boolean
    Return (value And flags) = flags
End Function

checkFlag(f, flags.f1) 'true
checkFlag(f, flags.f2) 'false
checkFlag(f, flags.f8) 'true
checkFlag(f, flags.f8 Or flags.f1) 'true
checkFlag(f, flags.f8 Or flags.f3) 'false
checkFlag(f, flags.f8 Or flags.f1 Or flags.f3) 'false

'.NET 4.0 之后可以采用内部方法 HasFlag 来判断
f.HasFlag(flags.f1) 'true
f.HasFlag(flags.f2) 'false
f.HasFlag(flags.f8 Or flags.f1) 'true

PS:
默认的Enum采用Integer存储数据,而一个Integer可以存储32个开关,这在一般情况下已经够用。
但若是你想要存储超过32个开关该怎么办呢?很简单,将Enum设置为可以存储64个开关的Long即可:
<Flags()> _
Enum flags As Long
    none = 0
    f1 = 1 << 0
    f2 = 1 << 1
    '...
    f64 = 1 << 63
End Enum
还不够?!!呃……
老老实实地多写几个Enum或者用Boolean吧……
有评论区的童鞋问 <Flags()> 是什么?
这是属性描述(或称为特性、元数据等),用以给下方的类型、方法、属性等添加一些描述性的信息和参数。
某些函数可以通过读取属性描述,来执行不同的处理方法,就比如下方的代码:
<Flags()> _
Enum flags1
    none = 0
    f1 = 1 << 0    '1
    f2 = 1 << 1    '2
    f3 = 1 << 2    '4
    f4 = 1 << 3    '8
    f5 = 1 << 4    '16
    f6 = 1 << 5    '32
    f7 = 1 << 6    '64
    f8 = 1 << 7    '128
End Enum

Enum flags2
    none = 0
    f1 = 1 << 0    '1
    f2 = 1 << 1    '2
    f3 = 1 << 2    '4
    f4 = 1 << 3    '8
    f5 = 1 << 4    '16
    f6 = 1 << 5    '32
    f7 = 1 << 6    '64
    f8 = 1 << 7    '128
End Enum

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim f1 As flags1 = flags1.f3 Or flags1.f5
    Dim f2 As flags2 = flags2.f3 Or flags2.f5

    MsgBox(f1.ToString) 'f3, f5
    MsgBox(f2.ToString) '20
End Sub
由此可以了解,<Flags()> 将指定的枚举 flags1 描述为一个 “Flags” 属性的Enum,当执行一些内部方法如tostringconsole.writeline时,会有更加本地化的方式来处理这些内容。

更多可以参考MSDN https://docs.microsoft.com/zh-cn/dotnet/api/system.attribute