Это общая проблема циркулярных ссылок. Об этом есть много, и общий вывод состоит в том, что их можно избежать как можно больше.
Поэтому вы правы, когда отказываетесь хранить в каждом классе коллекцию ссылок на другой класс. В VBA это приведет к утечкам памяти, поскольку сборщик мусора, основанный на подсчете ссылок, никогда не уничтожит объекты с круглыми ссылками, хотя группа, которую они образуют вместе, больше не нужна.
Но что, если вам действительно нужна двунаправленная ассоциация ?
Существуют различные решения для решения круговых ссылок, используя различные методы. В VBA вам нужен механизм для выпуска перекрестных ссылок, в каком-то месте, когда вы знаете, что они больше не нужны. Другими словами, вам нужно как-то управлять себя время жизни ссылок.
Возможной возможностью было бы поддерживать глобальный словарь групп живых. Когда вы хотите удалить группу, скажем, в какой-то процедуре, существующей где-то в коде, вы сначала освобождаете (пустую) свою коллекцию студентов. Это нарушит циркулярную ссылку, позволяющую сборщику мусора работать правильно. Ниже приводится скелет такой возможной реализации.
'In class clsUser:
Public id as String '<~~ could be any type of identifier, such as Integer
Public groups as New Dictionary
Public Sub subscribeToGroup(g as clsGroup)
Me.groups.add g.id, g
End Sub
Public Sub unsubscribeFromGroup(g as clsGroup)
Me.groups.Remove g.id
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''
'In class clsGroup:
Public id as String '<~~ could be any type of identifier, such as Integer
Public users as New Dictionary
Public Sub registerUser(u as clsUser)
Me.users.add u.id, u
End Sub
Public Sub unregisterUser(u as clsUser)
Me.users.Remove u.id
End Sub
Public Sub removeAllUsers() 'empty the users collection, break the circular reference
For Each u In users: u.unsubscribeFromGroup(Me): Next
users.RemoveAll
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''
У вас есть где-то (то есть глобальная переменная, или в каком-то классе под названием GroupManager и т.д.) Словарь групп и методы, чтобы создать или удалить группу.
Public AllGroups as Dictionary
Function addGroup(id as String) as clsGroup
Set addGroup = new clsGroup
addGroup.id = id
AllGroups.Add id, addGroup
End Function
Sub removeGroup(g as clsGroup)
' Explicitly Tell the group to free its users before going away.
' This would not be needed if we didn't have circular references!
g.removeAllUsers
AllGroups.Remove g.id
End Sub
Теперь круговые ссылки исчезли, и группа не будет уничтожена (без утечки памяти), потому что ничто не имеет каких-либо ссылок на него.