如何正确实现Scripting.Dictionary的Item属性以构建类型受限哈希表
错误原因
你收到必须实现Item属性的报错,核心原因是Implements Dictionary要求实现的成员签名必须和Scripting.Dictionary接口的原生定义完全匹配,你当前的Item属性签名、参数、返回值类型都不符合要求,同时缺少接口实现所需的命名规则适配。
正确实现方案
首先修正几个明显的语法错误:
- VBA没有
As Array合法返回值类型,存储数组需返回Variant - 数组是值类型,赋值应该用
Property Let而非Property Set - 接口实现的成员必须遵循
[接口名]_[成员名]的命名规则 - 你需要先声明私有
Supplier实例作为内部存储载体
完整实现代码如下:
Option Explicit ' 提前在工具-引用中勾选Microsoft Scripting Runtime Implements Dictionary ' 内部原生Dictionary存储实例 Private Supplier As New Scripting.Dictionary ' 自定义强类型Add方法 Public Sub Add(nom As String, jour As Date, temps As Integer) Supplier.Add nom, Array(jour, temps) End Sub ' 自定义强类型Item读取方法 Public Property Get Item(Key As String) As Variant Item = Supplier.Item(Key) End Property ' 自定义强类型Item赋值方法 Public Property Let Item(Key As String, jour As Date, temps As Integer) Supplier.Item(Key) = Array(jour, temps) End Property ' ---------------------- 以下为Dictionary接口强制要求实现的成员 ---------------------- ' 接口适配Item读取 Private Property Get Dictionary_Item(Key As Variant) As Variant Dictionary_Item = Supplier.Item(Key) End Property ' 接口适配Item值类型赋值 Private Property Let Dictionary_Item(Key As Variant, RHS As Variant) ' 加入类型校验避免非法写入 If VarType(Key) <> vbString Then Err.Raise vbObjectError + 1001, , "键必须为String类型" If Not IsArray(RHS) Or UBound(RHS) <> 1 Or VarType(RHS(0)) <> vbDate Or VarType(RHS(1)) <> vbInteger Then Err.Raise vbObjectError + 1002, , "值必须为Date+Integer格式的数组" End If Supplier.Item(Key) = RHS End Property ' 接口适配Item对象类型赋值(不需要可以直接抛错) Private Property Set Dictionary_Item(Key As Variant, RHS As Object) Err.Raise vbObjectError + 1003, , "本类不支持存储对象类型值" End Property ' 其余Dictionary接口成员也需要按规则实现,示例如下: Private Sub Dictionary_Add(Key As Variant, Item As Variant) If VarType(Key) <> vbString Then Err.Raise vbObjectError + 1004, , "键必须为String类型" If Not IsArray(Item) Or UBound(Item) <> 1 Or VarType(Item(0)) <> vbDate Or VarType(Item(1)) <> vbInteger Then Err.Raise vbObjectError + 1005, , "值必须为Date+Integer格式的数组" End If Supplier.Add Key, Item End Sub Private Property Get Dictionary_Count() As Long Dictionary_Count = Supplier.Count End Property Private Function Dictionary_Exists(Key As Variant) As Boolean Dictionary_Exists = Supplier.Exists(Key) End Function Private Sub Dictionary_Remove(Key As Variant) Supplier.Remove Key End Sub Private Sub Dictionary_RemoveAll() Supplier.RemoveAll End Sub Private Property Get Dictionary_Keys() As Variant Dictionary_Keys = Supplier.Keys End Property Private Property Get Dictionary_Items() As Variant Dictionary_Items = Supplier.Items End Property Private Property Get Dictionary_CompareMode() As CompareMethod Dictionary_CompareMode = Supplier.CompareMode End Property Private Property Let Dictionary_CompareMode(ByVal RHS As CompareMethod) Supplier.CompareMode = RHS End Property
方案合理性评估
该实现逻辑是可行的,根据你的使用场景可以做对应优化:
- 如果不需要你的类兼容原生Dictionary类型的传参要求,可以去掉
Implements Dictionary声明,仅保留自定义的强类型方法即可,不需要实现全部接口成员,代码更简洁 - 如果需要更高的类型安全性,可以把存储的数组替换为自定义类(比如命名为
WorkRecord,内部暴露Jour和Temps两个强类型属性),避免运行时判断数组元素类型的开销,可读性也更高
内容的提问来源于stack exchange,提问作者BenBouck
相关产品推荐
相关产品推荐

