使用早期绑定和Microsoft Scripting Runtime Library创建字典对象时,看起来有两个相同的类型名称用于同一事物:
Dim dict as Dictionary
Set dict = New Dictionary
和
Dim dict as Scripting.Dictionary
Set dict = new Scripting.Dictionary
似乎做同样的事情(至少到目前为止)。
我看到使用了As Scripting.Dictionary
语法by this resource,我看到As Dictionary
使用了by this (really great) resource语法,但我还没有看到任何比较。有关字典的MSDN文档可以是a literal joke,也可以是not explicitly related to VBA。
我不明白为什么我应该做额外的打字只是为了让我的函数声明更加拥挤如果我可以使用As Dictionary
,但我已经了解到VBA中的某些东西看起来像是等效实际上可以有微妙但显着的差异(例如Application.InputBox
与InputBox
)。
这些之间是否真的没有区别,或者我应该注意哪些细微差别?
答案 0 :(得分:9)
我不明白为什么我应该做额外的打字只是为了让我的函数声明更加拥挤[...]
它被称为完全限定类型。
执行此操作时:
Dim foo As Range
引用对话框中的优先级顺序确定的类型Range
以非常特定的顺序解析:
如果公开Range
类型的最顶层类型库是Excel类型库,则Range
代表Excel.Range
。
如果您的意思是Word.Range
,那么您就会遇到错误,并且对您声明的类型进行完全限定可以避免这些错误。
Scripting
库会公开Dictionary
类。因此,当您引用Scripting
类型库并执行此操作时:
Dim foo As Dictionary
您有权将该类型解析为Scripting.Dictionary
。但是,如果添加一个类模块并将其命名为Dictionary
,则突然所有这些非限定声明现在引用此自定义类,因为在查看外部引用之前,VBA类型解析将始终优先考虑当前项目中定义的类型。 / p>
当然你可以称之为“额外打字”。只要知道这两种方法都有利有弊。
Scripting.Dictionary
替换为适用于Mac的portable Dictionary
implementation。经验法则,编程与编写代码无关。这是关于阅读代码。编写易于阅读的代码,而不是编写速度快的代码。
答案 1 :(得分:4)
正如@braX在您的特定用例(早期绑定)中所说,它是相同的,因此Scripting.
可以被取消。
但是,有些情况可能会有所帮助(甚至需要)。例如,如果您在另一个Office应用程序中操作Excel,则会(使用早期绑定)写入
Dim XL as Excel.Application
因为您需要告诉VBA具体使用哪个应用程序。
但你可以继续写
Dim myWB as Workbook
并且VBA将知道它的卓越工作。但是,编写
可能更加用户友好Dim myWB as Excel.Workbook
这样,完全清楚发生了什么。
现在,对于大多数程序员而言,对于大多数程序员来说,它已经很清楚了,那很好,但是如果你在Word中进行编程并希望在Excel中操作Range对象该怎么办? 。写作
Dim myRange as Range
可能无法正常工作,因为VBA会将其解析为Word范围对象(因为您使用Word编写 - 请参阅MatMug的答案以获得更好的解释),这将导致错误进一步降低引用myRange.Offset(1)
时的代码行,例如,因为Word范围对象没有Offset
方法。因此,在这种情况下,它既是必要的又是用户友好的。
答案 2 :(得分:-3)
所有这些答案都说对了事,但最终都是错误的。让我们找出原因。以下是您可能会说Scripting.Dictionary和Dictionary相同的一些原因:
为什么我们会说它们不同?考虑:
Sub frontEnd()
Dim dictA As Scripting.Dictionary
Dim dictB As Dictionary
Set dictA = backEnd()
Set dictB = backEnd()
End Sub
Function backEnd() As Scripting.Dictionary
Dim myDict As Scripting.Dictionary
Set myDict = New Scripting.Dictionary
myDict("foo") = "bar"
myDict("bar") = "foo"
Set backEnd = myDict
End Function
运行此代码,您将发现VBA给您“类型不匹配”错误。因此,显然,不能将Scripting.Dictionary分配给Dictionary类型的变量。仅凭这一点,我就有理由将这两种类型视为不同。请注意,这对于在阳光下使用Variant的所有用户都是透明的,但是对于使用Option Explicit进行编程的我们来说,这是我们应该将这两种类型视为不同的强烈原因。
此外,接口可能相似,但绝对不一样!考虑:
Sub frontEnd()
Dim dictA As Scripting.Dictionary
Dim dictB As Dictionary
Set dictA = backEnd()
Set dictB = altBackEnd()
End Sub
Function backEnd() As Scripting.Dictionary
Dim myDict As Scripting.Dictionary
Set myDict = New Scripting.Dictionary
myDict("foo") = "bar"
myDict("bar") = "foo"
Set backEnd = myDict
End Function
Function altBackEnd() As Dictionary
Dim myDict As Dictionary
Set myDict = New Dictionary
myDict("foo") = "bar"
myDict("bar") = "foo"
Set altBackEnd = myDict
End Function
哦,哦! altBackEnd()函数中出现“找不到密钥”错误。显然,通过Scripting.Dictionary,您可以使用dict(“ foo”)=“ bar”语义隐式创建键/项对,但是Dictionary需要您使用dict.add()方法。像这样:
Sub frontEnd()
Dim dictA As Scripting.Dictionary
Dim dictB As Dictionary
Set dictA = backEnd()
Set dictB = altBackEnd()
End Sub
Function backEnd() As Scripting.Dictionary
Dim myDict As Scripting.Dictionary
Set myDict = New Scripting.Dictionary
myDict("foo") = "bar"
myDict("bar") = "foo"
Set backEnd = myDict
End Function
Function altBackEnd() As Dictionary
Dim myDict As Dictionary
Set myDict = New Dictionary
myDict.Add Key:="foo", Value:="bar"
myDict.Add Key:="bar", Value:="foo"
Set altBackEnd = myDict
End Function
作为最后一个演示为什么这些类型不同的原因,请尝试使用此版本替换backEnd()并查看会发生什么:
Function backEnd() As Scripting.Dictionary
Dim myDict As Scripting.Dictionary
Set myDict = New Scripting.Dictionary
myDict.Add Key:="foo", Value:="bar"
myDict.Add Key:="bar", Value:="foo"
Set backEnd = myDict
End Function
提示:显然词典使用键/值对,而脚本。字典使用键/项对。
作为最后的作业,使程序开始工作,发布一个断点,并使用VBE查看Scripting.Dictionary和Dictionary的结构。请注意,它们的实现方式有所不同!
结论:字典和脚本。字典...
Ergo,尽管两者都是Microsoft脚本运行时参考提供的,但它们是不同的。
最好使用Scripting.Dictionary,因为它的界面比Dictionary丰富得多(例如Scripting.Dictionary具有Remove()和RemoveAll()方法,而Dictionary没有。)