函数使用智能感知接受多个枚举
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!
其中 MyFunction
取 MyFlagEnum
值。
如果基础值具有特定含义并且它们是一成不变的并且 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
我在 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!
其中 MyFunction
取 MyFlagEnum
值。
如果基础值具有特定含义并且它们是一成不变的并且 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