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

Posted

技术标签:

【中文标题】函数使用智能感知接受多个枚举【英文标题】:Function uses intellisense to accept multiple Enums 【发布时间】:2017-08-15 15:23:55 【问题描述】:

我在 VBA 中声明了一个枚举

Enum myEnum
    valA = 3
    valB = 17
    valC = 20
End Enum

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

现在,如果我可以选择我的 Enum 中的值是 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。因此我想知道:

有没有办法将数组/不确定数量的变量传递给函数,同时仍然使用 Intellisense 来建议可能的值?

【问题讨论】:

不。 ParamArray 允许任意变量参数,但它是一种变体类型,因此没有智能感知。如果可能的话,位掩码(复合)是最优雅的方式。唯一的其他选择需要额外的设置代码,例如传递一个强类型数组。 你为什么不使用 2 的幂如果你知道这是怎么做的,它可以工作并且保持 IntelliSense?跨度> @Mat'sMug 不幸的是,我无法选择枚举中的值,它们是我想枚举的 magic numbers(微软提出的)的选择. 使用 2 的幂枚举作为查找值(在字典/选择案例实用程序函数中)以获取真实值? 微软想出了他们?如果这些值不是 2 的幂,则枚举不意味着用作复合值。实际的枚举是什么? 【参考方案1】:

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

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

这样做的原因是它们允许您使用按位逻辑来确定哪些位是“打开”的,给定一个复合值,例如 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

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

因此,要么您想出一种方法来“映射”单个“神奇的基础值”枚举成员以标记枚举成员(幂为 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 需要使用它们,则需要另一个函数将单个 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 需要做的第一件事是确定哪些单独的标志是“打开”的,然后GetFromFlag 每个人都可以获得单独的非标志枚举值。

这应该很有用:

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

【讨论】:

以上是关于函数使用智能感知接受多个枚举的主要内容,如果未能解决你的问题,请参考以下文章

ReSharper智能感知指向错误的功能

使用 c++ 在 vs2010 中进行智能感知

Visual Studio C++ 2005-2013 中的智能感知缺少函数定义

如何在 Visual Studio Code 中为 Unity 函数名称获取智能感知?

如何使用 undefinedWithCompletionsOf(value) 智能感知功能?

Visual Studio 智能感知不适用于 DHTMLX 套件 5