VB. Net Collections and the Key !!!

Hello All,

I'm having some smal problems with a collection in VB .Net .....

Public Class Reports

    Inherits CollectionBase
    Public Sub New()
    End Sub

    Public Function Add(ByVal objNewItem As Report) As Report


        Return objNewItem
    End Function

    Default Public Property Item(ByVal iIndex As Integer) As Report
            Return MyBase.InnerList.Item(iIndex)
        End Get
        Set(ByVal ReportObjectToBeAdded As Report)
            MyBase.InnerList.Item(iIndex) = ReportObjectToBeAdded
        End Set
    End Property

    Public Sub Remove(ByVal iIndex)
    End Sub

End Class

I know there isn't much going on here, but i just wanted to illustrate what i mean.

In VB 6.0 you could add a key (i think, it might have been called an index), when you are adding an item to a collection, and then from then on you could retrieve that object from the collection by using that Key. (Although you couldn't retrieve the key once it has been set).

This line MyBase.InnerList.Add(objNewItem) does return a index, which i think is the same thing, but i want to be able to set it ??

Is this possible ?? or have i got the whole thing upside down ??

Thanks in Advance.

Who is Participating?
Mike TomlinsonMiddle School Assistant TeacherCommented:
Hi DavidWilkinson,

The index is not the same as the key.  The index is the position of your item in the collection.  This can possibly change however, as you remove items from your collection and the items get shifted down to fill the gap left behind.

The key is string associated with your item that can be used to quickly retrieve that item regardless of its current position in the collection.

But why are you reinventing the wheel?  The Collection object from VB6 still exists in VB.Net:

    Dim Reports As Collection = New Collection
    Reports.Add("item1", "key1") ' You can add your instances of Report instead

>> Although you couldn't retrieve the key once it has been set

It is common practice to store the key in item itself.  Create a variable inside your Report class to the hold the key so you can easily use it.

If you need a more robust collection object, then comsider using the HashTable already built into .Net.  It works similarly to a Collection in that it has key/value pairs but it is much more powerful.  It works only on key values however.  You cannot access the items by index.  The HashTable has two very convient functions called ContainsKey() and ContainsValue() though that I use often.


If you want a user-definable value rather than a sequential index value as a key, then try deriving from DictionaryBase instead of CollectionBase.  The dictionary functionality gives you the ability to define a key (not necessarily numeric) for each value.  You then look up the values by their keys.  You lose the ability to say "Get me the third element" though.  You can use an enumerator to iterate sequentially through the values or you can look them up by the key values you gave them.  You'd have to do a totally custom collection to get both user-key AND sequential random access.
DavidWilkinsonAuthor Commented:
Hi Idle_Mind,

Many thanks for your super-quick respone.

As i'm sure you guessed, I'm quite experianced with VB 6.0 and have only started to look at VB .Net, mainly becuase i'm developing a flexible end-user Crystal Reports Viewer (and possibly designer) and i want to use the Dataset with ADO .Net.

If you have time, could you give be a brief description (possibly a example) of the HashTable, this is the first i've heard of it, and i'm intrigued ;o)

I'm going to Accept your answer, but to be honest I haven't asked many questions on Experts Exchange, so i might cock it up.

Thanks your your time.

Kind Regards


PS Thanks for your answer aslo drichards.

Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

DavidWilkinsonAuthor Commented:
I don't know if i'm allowed to do this once i've accepted an answer, but ......

Using the Collection object as Idle_Mind suggested, i can't do the For Each objLemon in objLemons (outside the actual class).

In VB 6 there was the NewEnum which you had to set the process ID to -4 etc

is there any similar function in VB .net

Kind Regards

Mike TomlinsonMiddle School Assistant TeacherCommented:
You have to implement the IEnumerable interface as shown below and then you can use your class in a For Each...Next statement:

Public Class Lemons
    Implements IEnumerable

    Private myCollection As Collection = New Collection

    Public Function GetEnumerator() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
        Return myCollection.GetEnumerator
    End Function

    Public ReadOnly Property count() As Integer
            Return myCollection.Count
        End Get
    End Property

    Public Sub add(ByRef Item As Object, Optional ByVal key As String = Nothing, _
        Optional ByVal before As Object = Nothing, Optional ByVal after As Object = Nothing)
        myCollection.Add(Item, key, before, after)
    End Sub

    Public Sub remove(ByVal key As String)
    End Sub

    Public Sub remove(ByVal index As Integer)
    End Sub

    Public ReadOnly Property item(ByVal key As String) As Object
            Return myCollection.Item(key)
        End Get
    End Property

    Public ReadOnly Property item(ByVal index As Integer) As Object
            Return myCollection.Item(index)
        End Get
    End Property

End Class
Mike TomlinsonMiddle School Assistant TeacherCommented:
Here is a very simple example of using a HashTable.  In this case, we are only using strings, but you can use object as the key or the value:

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

    Public Sub New()

        'This call is required by the Windows Form Designer.

        'Add any initialization after the InitializeComponent() call

    End Sub

    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
            End If
        End If
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents Label1 As System.Windows.Forms.Label
    Friend WithEvents NumericUpDown1 As System.Windows.Forms.NumericUpDown
    Friend WithEvents Button1 As System.Windows.Forms.Button
    Friend WithEvents Button2 As System.Windows.Forms.Button
    Friend WithEvents ListBox1 As System.Windows.Forms.ListBox
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.Label1 = New System.Windows.Forms.Label
        Me.NumericUpDown1 = New System.Windows.Forms.NumericUpDown
        Me.Button1 = New System.Windows.Forms.Button
        Me.Button2 = New System.Windows.Forms.Button
        Me.ListBox1 = New System.Windows.Forms.ListBox
        CType(Me.NumericUpDown1, System.ComponentModel.ISupportInitialize).BeginInit()
        Me.Label1.Location = New System.Drawing.Point(56, 8)
        Me.Label1.Name = "Label1"
        Me.Label1.Size = New System.Drawing.Size(224, 24)
        Me.Label1.TabIndex = 0
        Me.Label1.Text = "Label1"
        Me.NumericUpDown1.Location = New System.Drawing.Point(8, 8)
        Me.NumericUpDown1.Name = "NumericUpDown1"
        Me.NumericUpDown1.Size = New System.Drawing.Size(40, 20)
        Me.NumericUpDown1.TabIndex = 1
        Me.Button1.Location = New System.Drawing.Point(8, 40)
        Me.Button1.Name = "Button1"
        Me.Button1.Size = New System.Drawing.Size(88, 32)
        Me.Button1.TabIndex = 2
        Me.Button1.Text = "List Keys"
        Me.Button2.Location = New System.Drawing.Point(8, 80)
        Me.Button2.Name = "Button2"
        Me.Button2.Size = New System.Drawing.Size(88, 32)
        Me.Button2.TabIndex = 3
        Me.Button2.Text = "List Values"
        Me.ListBox1.Location = New System.Drawing.Point(104, 40)
        Me.ListBox1.Name = "ListBox1"
        Me.ListBox1.Size = New System.Drawing.Size(176, 212)
        Me.ListBox1.TabIndex = 4
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(292, 266)
        Me.Name = "Form1"
        Me.Text = "Form1"
        CType(Me.NumericUpDown1, System.ComponentModel.ISupportInitialize).EndInit()

    End Sub

#End Region

    Private myHash As Hashtable = New Hashtable

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim i As Integer
        Dim numEntries As Integer = 5

        For i = 1 To numEntries
            myHash.Add("Key" & i, "Item" & i)
        NumericUpDown1.Minimum = 1
        NumericUpDown1.Maximum = numEntries * 2
    End Sub

    Private Sub NumericUpDown1_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles NumericUpDown1.ValueChanged
        Dim key As String
        key = "Key" & NumericUpDown1.Value
        If myHash.ContainsKey(key) Then
            Label1.Text = myHash.Item(key)
            Label1.Text = "(No Such Key)"
        End If
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim key As String

        For Each key In myHash.Keys
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim value As String

        For Each value In myHash.Values
    End Sub

End Class
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.