VBA Разница между Сетью и Назначением - PullRequest
0 голосов
/ 13 мая 2018

Я читаю исходный код VBA-JSON, который находится по адресу:

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

В функции, которая создает дамп объектов JSON (начиная с символа "{")в память:

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)

и следующим:

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

Я искал в SO и нашел этот пост,что не рассеивает путаницу:

Что на самом деле делает ключевое слово Set в VBA?

При чтении кода я понимаю, что если синтаксический анализатор читает "{"или" [", тогда он должен использовать словарь для хранения чего-либо между" {"и"} "и коллекцию для хранения чего-либо между" ["и"] ", и если анализатор читает что-то отличное от этих двух, тогда это просто значение, может быть логическим или String или Integer и т. д.

Чего я не понимаю, так это разницы между Set и Assignment.«Set» скопирует адрес возвращаемой переменной json_ParseValue, а присваивание просто сделает еще одну копию возвращаемой переменной.Это потому, что в первом случае есть дополнительное требование изменить возвращаемый объект, чтобы он передавался по адресу (как в C ++, который мы используем &)?

Ответы [ 2 ]

0 голосов
/ 13 мая 2018

Три типа, на которые вы ссылаетесь: словарь , коллекция и массив . По сути, любая их комбинация может составлять структуру JSON.

Кто-то с большим количеством времени, вероятно, даст лучший ответ, но суть его (в моем слишком упрощенном толковании)

  • При присваивании значения переменной получается копия этого значения.

  • Set используется для объектов, поскольку вместо копирования объекта создается ссылка на объект.

Обычно, когда вы используете Set для присвоения ссылки на объект переменной, для этой переменной не создается копия объекта. Вместо этого создается ссылка на объект. Более чем одна переменная объекта может ссылаться на один и тот же объект. Поскольку такие переменные являются ссылками на объект, а не копиями объекта, любое изменение в объекте отражается во всех переменных, которые к нему относятся . Однако, когда вы используете ключевое слово New в операторе Set, вы фактически создаете экземпляр объекта. ( Источник )


Дополнительная информация:

0 голосов
/ 13 мая 2018

Как сказано в связанных вопросах и ответах, Set используется в VBA для назначения ссылки на объект. Ключевое слово Let может использоваться для присвоения значений, но ключевое слово Let в значительной степени устарело / избыточно.

Вот почему у вас есть следующие ключевые слова в определениях мутатора свойств:

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")

против

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

Две инструкции выглядят отличающимися только потому, что у одной есть ключевое слово Set, а у другой нет, однако реальная разница заключается в неявном вызове члена скрытого свойства с именем [_Default], который имеет атрибут VB_UserMemId = 0, который делает этот член классом член по умолчанию .

Путаница проистекает из неявных вызовов членов по умолчанию , которые заставляют код говорить что-то, а на самом деле делают что-то еще.

Rubberduck (проект надстройки OSS VBIDE, которым я управляю) имеет проверку кода, которая находит неявные назначения членов по умолчанию в раннем коде:

Неявное назначение членов по умолчанию

Такие присваивания выглядят так, как будто они присваивают переменную объекта типу значения на поверхности, но они фактически присваивают элемент этого объекта по умолчанию, неявно. Рассмотрите возможность явного обращения к элементу по умолчанию для улучшения читаемости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...