函数使用智能感知接受多个枚举

Function uses intellisense to accept multiple Enums

我在 VBA

中声明了一个枚举
Enum myEnum
    valA = 3
    valB = 17
    valC = 20
End Enum

我想要一个函数,它接受此枚举指定的值的任意组合,并在您输入它们时使用 Intellisense。即,它会提示我可以输入的可能值。

现在,如果我可以选择枚举中的值是 2 的幂,那么我可能会按照 Chip Pearson 在 his section on Composite Values 中建议的那样去做,即

Function myFunction(val As myEnum)
    '...
End Function

用法

Debug.Print myFunction(valA + valB) 'with intellisense

但是我的枚举不遵循这种模式,所以我无法想出辨别输入的是 valA + valB 还是 valC 之类的。因此我想知道:

有没有办法将 array/undetermined 个变量传递给一个函数,同时仍然使用 Intellisense 来建议可能的值?

不,没有。 Flag 枚举正是为此使用 2 的幂。

Public Enum Foo
    V1 = 2 ^ 0
    V2 = 2 ^ 1
    V3 = 2 ^ 2
    V4 = 2 ^ 3
    V5 = 2 ^ 4
    '...
End Enum

这样做的原因是它们允许您使用按位逻辑来确定哪些位是 "on",给定一个复合值,例如 5 只能是 4 + 1 :

Power    2^5  2^4 2^3  2^2  2^1  2^0 
Value     32   16   8    4    2    1
Bit        0    0   0    1    0    1

一样,另一种方法是使用 ParamArray 参数,但这只能是 Variant,并且只能传递 ByRef ,这不仅意味着您失去了 IntelliSense,还失去了传递参数值 ByVal 的语义安全性(好吧,您的代码 隐式 传递它 ByRef 无论如何)。

因此,要么你想出一种方法来 "map" 个别 "magic underlying values" 枚举成员来标记枚举成员(具有 2 的幂),要么你放弃 IntelliSense。

Private Function GetFlag(ByVal value As MyEnum) As MyFlagEnum
    Static converter As Scripting.Dictionary
    If converter Is Nothing Then
        Set converter = New Scripting.Dictionary
        With converter
            .Add MyEnum.valA, MyFlagEnum.ValueA
            .Add MyEnum.valB, MyFlagEnum.ValueB
            .Add MyEnum.valC, MyFlagEnum.ValueC
            .Add MyEnum.valD, MyFlagEnum.ValueD
            .Add MyEnum.valE, MyFlagEnum.ValueE
        End With
    End If
    GetFlag = converter(value)
End Function

然后你可以将它们组合起来拉取映射值后:

Debug.Print MyFunction(GetFlag(valA) + GetFlag(valB)) ' intellisense everywhere!

其中 MyFunctionMyFlagEnum 值。

如果基础值具有特定含义并且它们是一成不变的并且 MyFunction 需要使用它们,则您需要另一个函数来 "unwrap" 将单个 FlagEnum 值转换为单个 "MyEnum" 值:

Private Function GetFromFlag(ByVal value As MyFlagEnum) As MyEnum
    Static converter As Scripting.Dictionary
    If converter Is Nothing Then
        Set converter = New Scripting.Dictionary
        With converter
            .Add MyFlagEnum.ValueA, MyFlagEnum.valA
            .Add MyFlagEnum.ValueB, MyFlagEnum.valB
            .Add MyFlagEnum.ValueC, MyFlagEnum.valC
            .Add MyFlagEnum.ValueD, MyFlagEnum.valD
            .Add MyFlagEnum.ValueE, MyFlagEnum.valE
        End With
    End If
    GetFromFlag = converter(value)
End Function

然后再次使用该函数 与单独的 未组合 。所以 MyFunction 需要做的第一件事是确定哪些是单独的标志 "on",然后 GetFromFlag 每个标志都得到单独的非标志枚举值。

这应该有用:

Private Function HasFlag(ByVal composite As Long, ByVal flag As Long) As Boolean
    HasFlag = (composite And flag) = flag
End Function