【问题标题】:VBA Linking two Objects BidirectionallyVBA双向链接两个对象
【发布时间】:2015-11-25 00:33:30
【问题描述】:

我有两个对象,clsGroup 和 clsUser。用户和组是独立的对象。

  • 每个用户可以属于任意数量的组。
  • 每个组可以包含任意数量的用户。

VBA 不是存储属于每个用户的组列表,以及属于每个对象中每个组的用户列表,VBA 是否提供任何方法来链接它们,以便我们可以从用户对象中获取与该用户关联的组,并且从组对象中我们可以获得与该组关联的用户列表?

我试图避免在用户和组中创建集合,因为同步会出现问题。

【问题讨论】:

    标签: vba object collections relation bidirectional


    【解决方案1】:

    这是循环引用的普遍问题。那里有很多关于它的东西,一般的结论是它们是要尽可能避免的。

    因此,当您拒绝在每个类中存储对另一个类的引用集合时,您是正确的。在 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
    

    现在,循环引用消失了,组将被销毁(没有内存泄漏),因为没有任何东西持有对它的任何引用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-28
      • 1970-01-01
      • 1970-01-01
      • 2011-11-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多