Excel VBA: уничтожает ли коллекция объектов каждый отдельный объект? - PullRequest
9 голосов
/ 17 апреля 2011

Скажем, у меня есть коллекция MyCollection объектов MyClass.

Вызывает ли Set MyCollection = Nothing деструктор каждого содержащегося в нем объекта или я должен позаботиться о настройке каждого объекта = Nothing по отдельности?

Я, очевидно, беспокоюсь о причинах утечки памяти.

Dim MyCollection As Collection
Set MyCollection = New Collection
... 'add objects of type MyClass here
Set MyCollection = Nothing 

Вызывает ли уничтожение этого класса каждый деструктор каждого объекта?

Ответы [ 2 ]

10 голосов
/ 17 апреля 2011

Все объекты MyClass будут уничтожены при уничтожении MyCollection, если на них нет ссылок где-то еще.

VBA использует счетчик ссылок на класс.Он сбрасывается по одному каждый раз, когда есть ссылка на класс, и убирает по одному каждый раз, когда ссылка уничтожается.Пока MyCollection является чем-то и находится в области видимости, каждый счетчик ссылок MyClass, содержащийся в нем, будет по крайней мере один.Если счетчик ссылок ровно один, то при уничтожении MyCollection счетчик ссылок каждого элемента сбрасывается до нуля, и он будет собирать мусор.

Последняя переменная MyClass в середине вашей подпрограммы будет ссылаться на один экземпляр MyClass, если только вы неявно установить его в Nothing.Одна переменная класса вряд ли вызовет заметную проблему с памятью.

Sub MakeClassColl()

    Dim MyCollection As Collection
    Dim i As Long
    Dim clsMyClass As MyClass

    Set MyCollection = New Collection

    For i = 1 To 3
        Set clsMyClass = New MyClass
        MyCollection.Add clsMyClass
        'Check1
    Next i

    Set MyCollection = Nothing
    'Check2

End Sub

Check1:

  • i = 1: MyClass1 (экземпляр 1) имеет счетчик ссылок 2Один для переменной, другой для коллекции
  • i = 2: MyClass1 имеет значение rc 1 (потерянный clsMyClass, все еще имеет коллекцию), MyClass2 имеет значение rc 2
  • i = 3: MyClass1 по-прежнему 1, MyClass2 падает до 1, MyClass3 имеет rc 2

Check2:

  • Каждый экземпляр MyClassi в коллекции уменьшается на единицу.MyClass1 и 2 обнуляются.MyClass3 падает до 1, потому что clsMyClass все еще ссылается на него (я не уничтожил clsMyClass после добавления его в коллекцию).
2 голосов
/ 17 апреля 2011

Краткий ответ - да. В приведенном ниже примере, который очень похож на ваш, за исключением того, что он показывает один конкретный способ создания экземпляров MyClass, все отдельные экземпляры MyClass будут уничтожены сразу после уничтожения коллекции:

Dim MyCollection As Collection
Set MyCollection = New Collection

Call MyCollection.Add(New MyClass)
Call MyCollection.Add(New MyClass)
Call MyCollection.Add(New MyClass)

Set MyCollection = Nothing

Чем дольше ответ, тем больше. Ответ - «да», если единственная ссылка на содержащиеся объекты - это та, что содержится в коллекции, как в вашем простом примере. VBA будет знать, что на все ваши экземпляры MyClass больше нет ссылок, и уничтожит их. (Это приведет к вызову метода Class_Terminate каждого экземпляра объекта.)

Но вы должны быть осторожны, если вы делали другие ссылки на эти объекты. В заявлении Set MyCollection = Nothing нет ничего волшебного. Это тот факт, что это приводит к тому, что VBA уничтожает коллекцию, что, в свою очередь, приводит к уничтожению объекта внутри. (И, конечно, коллекция уничтожается этой строкой, только если MyCollection ссылается на единственную ссылку на нее.)

Хороший источник, чтобы узнать больше о том, как время жизни объектов VBA - это старое Руководство программиста Visual Basic 6.0, в частности, раздел «Ссылки на объекты и подсчет ссылок»:

http://msdn.microsoft.com/en-us/library/aa263495(v=VS.60).aspx

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