Erik Porter's Blog

Life and Development at Microsoft and Other Technology Discussions

News

    Strongly Typed Collections

    Darren and Robert having been talking a bit about Strongly Typed Collections and it's all good stuff, but what I'm a little lost on is I don't see any mention of inheriting from System.Collections.CollectionBase.  This class already Implements IList, ICollection & IEnumberable.  My theory is always...the less work, the better.  CollectionBase is great and helps you implement Strongly Typed Collections really quickly.  Here's a quick example.

    Public C

    lass Person

         Private m_ID As
    Guid
         Private m_FirstName As String
    = ""
         Private m_LastName As String
    = ""

         Public Sub New(ByVal FirstName As String, ByVal LastName As String
    )
              Me
    .m_ID = Guid.NewGuid
              Me
    .m_FirstName = FirstName
              Me
    .m_LastName = LastName
         End
    Sub

        
    Public Sub New(ByVal ID As Guid, ByVal FirstName As String, ByVal LastName As String)

              Me
    .m_ID = ID
              Me
    .m_FirstName = FirstName
              Me
    .m_LastName = LastName
         End
    Sub

        
    Public ReadOnly Property ID() As
    Guid
             
    Get
                  
    Return
    m_ID
              End
    Get
        
    End
    Property

        
    Public Property FirstName() As
    String
             
    Get
                  
    Return
    m_FirstName
              End
    Get
             
    Set(ByVal Value As String
    )
                   m_FirstName = Value
              End
    Set
        
    End
    Property

        
    Public Property LastName() As
    String
             
    Get
                  
    Return
    m_LastName
              End
    Get
             
    Set(ByVal Value As String
    )
                   m_LastName = Value
              End
    Set
        
    End
    Property

    End
    Class

    Public
    Class
    People
         Inherits
    CollectionBase

         Public Function Add(ByVal Person As Person) As
    Integer
             
    Return Me
    .InnerList.Add(Person)
         End
    Function

        
    Public Function Add(ByVal FirstName As String, ByVal LastName As String) As
    Person
              Dim NewPerson As New
    Person(FirstName, LastName)

              Me
    .InnerList.Add(NewPerson)

              Return
    NewPerson
         End
    Function

        
    Public Function Add(ByVal ID As Guid, ByVal FirstName As String, ByVal LastName As String) As
    Person
              Dim NewPerson As New
    Person(ID, FirstName, LastName)

              Me
    .InnerList.Add(NewPerson)

              Return
    NewPerson
         End
    Function

        
    Default Public ReadOnly Property Item(ByVal Index As Integer) As
    Person
             
    Get
                  
    If Index > Me.InnerList.Count - 1 OrElse Index < 0
    Then
                       
    Throw New
    IndexOutOfRangeException("Index out of Range")
                  
    Else
                       
    Return DirectCast(Me
    .InnerList.Item(Index), Person)
                   End
    If
             
    End
    Get
        
    End
    Property

        
    Default Public ReadOnly Property Item(ByVal ID As Guid) As
    Person
             
    Get
                  
    Dim Index As Integer = Me
    .IndexOf(ID)
                   If Index = -1
    Then
                       
    Throw New ArgumentException("No Person was found with the provided ID", "ID")

                   Else
                       
    Return DirectCast(Me.InnerList.Item(Index), Person)
                   End
    If
             
    End
    Get
        
    End
    Property

        
    Default Public ReadOnly Property Item(ByVal FirstName As String, ByVal LastName As String) As
    Person
             
    Get
                  
    Dim Index As Integer = Me
    .IndexOf(FirstName, LastName)
                   If Index = -1
    Then
                       
    Throw New
    ArgumentException("No Person was found with the provided FirstName and LastName")
                  
    Else
                       
    Return DirectCast(Me
    .InnerList.Item(Index), Person)
                   End
    If
             
    End
    Get
        
    End
    Property

        
    Public Function IndexOf(ByVal ID As Guid) As
    Integer
             
    Dim FoundPersonIndex As Integer
    = -1

              For i As Integer = 0 To Me
    .InnerList.Count - 1
                   If DirectCast(Me.InnerList.Item(i), Person).ID.Equals(ID)
    Then
                       
    FoundPersonIndex = i
                        Exit
    For
                  
    End
    If
             
    Next

             
    Return
    FoundPersonIndex
         End
    Function

        
    Public Function IndexOf(ByVal FirstName As String, ByVal LastName As String) As
    Integer
             
    Dim CurrentPerson As
    Person
              Dim FoundPersonIndex As Integer
    = -1

              For i As Integer = 0 To Me
    .InnerList.Count - 1
                   CurrentPerson = DirectCast(Me
    .InnerList.Item(i), Person)
                   If CurrentPerson.FirstName = FirstName AndAlso CurrentPerson.LastName = LastName
    Then
                       
    FoundPersonIndex = i
                        Exit
    For
                  
    End
    If
             
    Next

             
    Return
    FoundPersonIndex
         End
    Function

        
    Public Sub Remove(ByVal Index As Integer
    )
              Me
    .InnerList.RemoveAt(Index)
         End
    Sub

        
    Public Sub Remove(ByVal Person As
    Person)
              Me
    .InnerList.Remove(Person)
         End
    Sub

        
    Public Sub Remove(ByVal ID As
    Guid)
              Dim Index As Integer = Me
    .IndexOf(ID)
              If Index = -1
    Then
                  
    Throw New
    ArgumentException("No Person was found to remove with the provided ID", "ID")
             
    Else
                  
    Me
    .InnerList.RemoveAt(Index)
              End
    If
        
    End
    Sub

    End
    Class

    This may look like a lot of code, but it's really not.  It took me all of 15 minutes to setup from scratch.  Now you can use it just like any other Strongly Typed Collection.

    Dim PeopleList As New People
    Dim PersonIndex As
    Integer

    PersonIndex = PeopleList.Add(New
    Person("Erik", "Porter"))
    PeopleList.Add("Stacey", "Dyer")

    MessageBox.Show(PeopleList(PersonIndex).LastName)
    MessageBox.Show(PeopleList("Stacey", "Dyer").ID.ToString)

    So if you're thinking about creating your own Collection definitely take a look at CollectionBase.  Extremely easy and fun (well for me anyway)!

    <update>

    I originally had a lot of Overloads Keywords in the Collection, which were not necessary.  That's what I get for copying old code instead of typing it out myself.  I took them out.

    </update>

    Comments

    TrackBack said:

    HumanCompiler - Erik Porter Blog
    # July 27, 2003 9:42 PM

    Robert McLaws said:

    My problem was twofold: a) I could not easily return a value by a string instead of by an index. b) all I was doing was name/value pairs anyways, and inheriting from NameValueCollection allowed me to accomplish what I needed to. c) I really didn't want to spend the next three days trying to figure out how it worked when really the NVC did what I needed it to do without compromising my design.
    # July 27, 2003 10:55 PM

    HumanCompiler said:

    Gotchya, well, you guys gave me an excuse to blog about something I do in almost all my projects. ;) Hopefully someone will find a use for it! :)
    # July 27, 2003 11:00 PM

    Adam Kinney said:

    That's what mine look like. The first time I actually made typed collection, I didn't know about the collectionbase class. That was a waste of typing. Now I my code looks pretty similiar to yours for typed collections.
    # July 28, 2003 1:25 PM

    Rob Zelt said:

    The other thing that I think is important to mention regarding Strongly Typed Collections is details about Implements IBindingList to allow use with datagrid controls.
    # July 30, 2003 8:18 PM

    HumanCompiler said:

    True, very good point, Rob. And actually, not just DataGrids, but everything that supports DataBinding in WindowsForms
    # July 30, 2003 8:21 PM