如何:将自定义集合转换为 Visual Basic 类型化集合

更新:2007 年 11 月

Visual Basic 6.0 自定义集合将集合内容限制到一个特定类。这也称为一个类型化集合。Visual Basic 2008 提供一些选项,可从 Visual Basic 6.0 自定义集合创建类型化类。本主题包含三个过程,每个过程介绍一个不同选项。

本主题假定已使用“类生成器实用工具”创建了 Visual Basic 6.0 自定义集合。此类集合具有以下成员:

  • Add   将自定义类的新实例添加到集合。

  • Item   根据集合索引从集合返回一个实例。

  • Count   返回集合中实例的数目。

  • Remove   根据集合索引从集合移除一个实例。

  • Enumeration   支持使用 For Each 语法进行枚举。

使用升级向导创建集合

  • 在 Visual Basic 2008 中打开 Visual Basic 6.0 项目。对于包含 Tree 类实例的集合类 Forest,升级后的代码如下所示。此方法的优点是无需更改代码。

    ' For this example, the Tree class has no members.
    Option Strict Off
    Option Explicit On
    Friend Class Tree
    End Class
    
    Friend Class Forest
      Implements System.Collections.IEnumerable
      'local variable to hold collection
      Private mCol As Collection
    
      Public Function Add(Optional ByRef sKey As String = "") As Tree
        'create a new object
        Dim objNewMember As Tree
        objNewMember = New Tree
        'set the properties passed into the method
        If Len(sKey) = 0 Then
          mCol.Add(objNewMember)
        Else
          mCol.Add(objNewMember, sKey)
        End If
        'return the object created
        Add = objNewMember
        'UPGRADE_NOTE: Object objNewMember may not be destroyed until it is garbage collected. Click for more: 'ms-help://MS.MSDNQTR.80.en/commoner/redir/redirect.htm?keyword="vbup1029"'
    
        objNewMember = Nothing
      End Function
    
      Default Public ReadOnly Property Item(ByVal vntIndexKey _
        As Object) As Tree
        Get
          'used when referencing an element in the collection
          'vntIndexKey contains either the Index or Key to the collection,
          'this is why it is declared as a Variant
          'Syntax: Set foo = x.Item(xyz) or Set foo = x.Item(5)
          Item = mCol.Item(vntIndexKey)
        End Get
      End Property
    
      Public ReadOnly Property Count() As Integer
        Get
          'used when retrieving the number of elements in the
          'collection. Syntax: Debug.Print x.Count
          Count = mCol.Count()
        End Get
      End Property
    
      'UPGRADE_NOTE: NewEnum property was commented out. Click for more: 'ms-help://MS.MSDNQTR.80.en/commoner/redir/redirect.htm?keyword="vbup1054"'
    
      'Public ReadOnly Property NewEnum() As stdole.IUnknown
        'Get
          'this property allows you to enumerate
          'this collection with the For...Each syntax
          'NewEnum = mCol._NewEnum
        'End Get
      'End Property
    
      Public Function GetEnumerator() As System.Collections.IEnumerator _
        Implements System.Collections.IEnumerable.GetEnumerator
        'UPGRADE_TODO: Uncomment and change the following line to return the collection enumerator. Click for more: 'ms-help://MS.MSDNQTR.80.en/commoner/redir/redirect.htm?keyword="vbup1055"'
    
        'GetEnumerator = mCol.GetEnumerator
      End Function
    
      Public Sub Remove(ByRef vntIndexKey As Object)
        'used when removing an element from the collection
        'vntIndexKey contains either the Index or Key, which is why
        'it is declared as a Variant
        'Syntax: x.Remove(xyz)
        mCol.Remove(vntIndexKey)
      End Sub
    
      'UPGRADE_NOTE: Class_Initialize was upgraded to Class_Initialize_Renamed. Click for more: 'ms-help://MS.MSDNQTR.80.en/commoner/redir/redirect.htm?keyword="vbup1061"'
    
      Private Sub Class_Initialize_Renamed()
        'creates the collection when this class is created
        mCol = New Collection
      End Sub
      Public Sub New()
        MyBase.New()
        Class_Initialize_Renamed()
      End Sub
    
      'UPGRADE_NOTE: Class_Terminate was upgraded to Class_Terminate_Renamed. Click for more: 'ms-help://MS.MSDNQTR.80.en/commoner/redir/redirect.htm?keyword="vbup1061"'
    
      Private Sub Class_Terminate_Renamed()
        'destroys collection when this class is terminated
        'UPGRADE_NOTE: Object mCol may not be destroyed until it is garbage collected. Click for more: 'ms-help://MS.MSDNQTR.80.en/commoner/redir/redirect.htm?keyword="vbup1029"'
    
        mCol = Nothing
      End Sub
      Protected Overrides Sub Finalize()
        Class_Terminate_Renamed()
        MyBase.Finalize()
      End Sub
    End Class
    

.NET Framework 和 Visual Basic 2008 提供了几个泛型集合。使用泛型集合的优点是只需很少代码即可实现类。

使用泛型集合创建集合

  1. 创建类定义。下面是 Tree 类的一个示例:

    Public Class Tree
        Public Species As String
    End Class
    
  2. 从 .NET Framework 创建一个泛型列表类。此声明实质上代替了名为“使用升级向导创建集合”的上述过程中的整个 Forest 类。

    Dim forest As New System.Collections.Generic.List(Of Tree)
    
  3. 编写代码访问列表对象。下面的代码将 Tree 类的 5 个实例添加到集合,然后显示这些实例。

    For count As Integer = 1 To 5
        Dim sapling As New Tree
        sapling.Species = "oak"
        Forest.Add(sapling)
    Next
    
    For Each sapling As Tree In Forest
        MsgBox(sapling.Species)
    Next
    

.NET Framework 包括 CollectionBase 类。通过从 CollectionBase 继承可创建类型化集合。此方法使用的代码比使用升级向导少,但比泛型解决方案多。它比泛型解决方案更灵活,因为程序员可以向集合类添加更多成员。

从 CollectionBase 类创建集合

  1. 创建类定义。下面是 Tree 类的一个示例:

    Public Class Tree
        Public Species As String
    End Class
    
  2. 创建一个从 CollectionBase 类继承的类。至少添加一个 Add 方法和一个 Item 属性。这样可使集合类强类型化。

    Class TreeCollection
      Inherits System.Collections.CollectionBase
    
      Public Sub Add(ByVal value As Tree)
        Me.List.Add(value)
      End Sub
    
      Default Public Property Item(ByVal index As Integer) As Tree
          Get
              Return CType(Me.List(index), Tree)
          End Get
          Set(ByVal value As Tree)
              If index <= Me.Count - 1 Then
                  Me.List(index) = value
              Else
                  Throw New IndexOutOfRangeException()
              End If
          End Set
      End Property
    End Class
    
  3. 编写代码访问列表对象。下面的代码将 Tree 类的 5 个实例添加到集合,然后显示这些实例。

    Dim forest As New TreeCollection
    
    For count As Integer = 1 To 5
        Dim sapling As New Tree
        sapling.Species = "oak"
        Forest.Add(sapling)
    Next
    
    For Each sapling As Tree In Forest
        MsgBox(sapling.Species)
    Next
    

请参见

参考

List

CollectionBase

IEnumerable