设置和分配之间的VBA差异

时间:2018-05-13 18:47:54

标签: vba parsing

我正在阅读VBA-JSON的源代码,该代码位于:

https://github.com/VBA-tools/VBA-JSON/blob/master/JsonConverter.bas

在将JSON对象(以" {" char开头)转储到内存的函数中:

starttime = datetime.strptime(' '.join([now.year, e[4], e[0], '%Y %a %d %b %I:%M%p').strftime('%Y%m%d%H%M%S')
endtime = datetime.strptime(' '.join([now.year, e[4], e[1]]), '%Y %a %d %b %I:%M%p').strftime('%Y%m%d%H%M%S')

global epg_data

epg_data = u"""\
<programme start="{starttime} +0100" stop="{endtime} +0100" channel="{channel}">
    <title lang="eng">{e5}</title>
    <desc lang="eng">{e2} {e3}</desc>
    <icon src="{div_list2}" />
    <country>UK</country>
</programme>""".format(channel=escape(channel), starttime=starttime, 
    endtime=endtime,e5=escape(e5), e2=escape(e2), e3=escape(e3), 
    div_list2=escape(div_list2))

有什么区别:

Private Function json_ParseObject(json_String As String, ByRef json_Index As Long) As Dictionary
Dim json_Key As String
Dim json_NextChar As String

Set json_ParseObject = New Dictionary
json_SkipSpaces json_String, json_Index
If VBA.Mid$(json_String, json_Index, 1) <> "{" Then
    Err.Raise 10001, "JSONConverter", json_ParseErrorMessage(json_String, json_Index, "Expecting '{'")
Else
    json_Index = json_Index + 1

    Do
        json_SkipSpaces json_String, json_Index
        If VBA.Mid$(json_String, json_Index, 1) = "}" Then
            json_Index = json_Index + 1
            Exit Function
        ElseIf VBA.Mid$(json_String, json_Index, 1) = "," Then
            json_Index = json_Index + 1
            json_SkipSpaces json_String, json_Index
        End If

        json_Key = json_ParseKey(json_String, json_Index)
        json_NextChar = json_Peek(json_String, json_Index)
        If json_NextChar = "[" Or json_NextChar = "{" Then
            Set json_ParseObject.Item(json_Key) = json_ParseValue(json_String, json_Index)
        Else
            json_ParseObject.Item(json_Key) = json_ParseValue(json_String, json_Index)
        End If
    Loop
End If
End Function

以下一个:

Set json_ParseObject.Item(json_Key) = json_ParseValue(json_String, json_Index)

我搜索了SO并找到了这篇文章,这并没有消除这种混淆:

What does the keyword Set actually do in VBA?

通过阅读代码,我理解如果解析器读取&#34; {&#34;或者&#34; [&#34;然后它需要使用一个字典来保存&#34; {&#34;和&#34;}&#34;,以及在#34; [&#34;和&#34;]&#34;,如果解析器读取的不是那两个,那么它只是一个值,可以是布尔值或字符串或整数等。

我不能得到的是Set和Assignment之间的区别。 &#34;设置&#34;将复制json_ParseValue的返回变量的地址,并且赋值只是生成返回变量的另一个副本。是因为在第一种情况下,还需要修改返回的对象,因此必须通过地址传递(就像我们使用的C ++中那样)?

2 个答案:

答案 0 :(得分:3)

正如链接的Q&amp; A所说,Set在VBA中用于分配对象引用。 Let关键字可用于分配值,但Let关键字几乎已过时/冗余。

这就是为什么你在属性mutator定义中有这些关键字的原因:

Private mSomething As Variant

Public Property Let Something(ByVal value As Variant)
    mSomething = value ' value is a primitive
End Property

Public Property Set Something(ByVal value As Variant)
    Set mSomething = value ' value is an object reference
End Property

到目前为止,这么好。这个区别:

Set json_ParseObject.Item(json_Key) = json_ParseValue(json_String, json_Index)

而且:

json_ParseObject.Item(json_Key) = json_ParseValue(json_String, json_Index)

这是因为json_ParseValue返回的Variant可以容纳任何内容,包括对象引用或简单值,那么在分配引用时需要使用Set关键字,并离开在分配值时输出(或使用Let关键字)。

如果不查看实施细节并确切了解返回的内容,就无法判断,但Let分配可能会分配给默认成员 - 而且默认的成员调用是隐式的,确实让人感到困惑。

与您在Excel VBA中分配单元格值完全相同:

Dim r As Range
Set r = ActiveSheet.Range("A1")

VS

Dim r As Double
r = ActiveSheet.Range("A1") 'implicit call to ActiveSheet.Range("A1").[_Default]

这两个说明看起来只是因为一个有Set个关键字而另一个没有,但真正的不同之处在于隐式成员对隐藏的成员调用名为[_Default]的属性,具有VB_UserMemId = 0属性,该属性使该成员成为类&#39; 默认会员

混淆源于隐式默认成员调用,它使代码某些东西,实际上其他东西。

Rubberduck(我管理的OSS VBIDE加载项项目)有一个代码检查,用于在早期绑定代码中查找隐式默认成员分配:

  

隐式默认会员分配

     

这样的赋值看起来像是将对象变量赋值给表面上的值类型,但它们实际上是隐式地分配该对象的默认成员。考虑明确引用默认成员,以提高可读性。

答案 1 :(得分:2)

您所指的三种类型是字典集合数组。基本上,这些组合可以构成JSON结构。

有更多时间的人可能会给出更好的答案,但其中的要点是(在我的过度简化的解释中),

  • 为变量指定值会使该值的副本

  • Set用于对象,因为它不会复制对象,而是为对象创建引用

  

通常,使用Set将对象引用分配给变量时,不会为该变量创建对象的副本。而是创建对对象的引用。 多个对象变量可以引用同一个对象。因为这些变量是对象的引用而不是对象的副本,所以对象中的任何更改都会反映在引用的所有变量中它即可。但是,在Set语句中使用New关键字时,实际上是在创建对象的实例。 <子>(Source

更多信息: