Creating a strongly-typed enumerable collection?

  • Thread starter Michael K. Walter
  • Start date
M

Michael K. Walter

I'd like to create a strongly-typed collection of objects that are indexed
by a string value (key is a string). I'd also like to allow users to iterate
over the collection using a For-each loop where an object of the contained
type is returned (instead of just the standard DictionaryEntry object).

- only allow objects of type MyObj to be added to the collection
- return a MyObj type in the For-each loop

What's the best way to do this?

I tried to have my collection class inherit from DictionaryBase but I had
trouble getting it to return MyObj objects in the For-each. By default its
retruning DictionaryEntry objects and it wouldn't let me override the
inherited GetEnumerator() function.

I also looked at inheriting from CollectionBase but this takes an integer
for the key values.

Is creating a class that implements IEnumerable and contains a private
collection object the way to go here?

Thanks in advance for the help/advice.

Michael
 
S

Shawn Hogan

I ran into a similar problem the way that i solved it was to have a class
that inherited from CollectionBase. This class also contained a SortedList.
Anytime i added something to the list object of the collectionBase i added
it to the sorted list. By doing this i was able to access my items by key or
by index.

Shawn
 
M

Michael K. Walter

Thanks for the note Shawn.

I've tried a number of options (including your suggestion) and, while I can
set this up using various collection types as my base, I still end up in
situation where I have to have the end users of my collection cast to the
appropriate type inside of the For-each loop. So far, I've had it return
either a DictionaryEntry or generic Object type in the For-Each that I had
to manipulate/cast to MyObj type before using the retrieved object. I was
trying to avoid this but I'm beginning to think that this cannot be done in
..Net (like I can in VB6).

Example:

Dim d1 as New Dog("Duncan","Golden Retriever")
Dim d2 as New Dog("Louie", "Lab")
Dim d3 as New Dog("Butch","Beagle")

Dim Kennel as New DogCollection

Kennel.Add(d1)
Kennel.Add(d2)
Kennel.Add(d3)

Dim o as Object
Dim d as Dog

For Each o In Kennel
d = CType(o, Dog)
Console.Write(d.Name)
Next

But I'm trying to get the last lines to look like this (no Object variable
declaration or Cast required):

Dim D as Dog

For Each d in Kennel
Console.Write(d.Name)
Next

Even using IEnumerable/IEnumerator didn't help since the IEnumerator
Current() property returns a generic Object type (and I couldn't get it
compile when I changed the return type to Dog).

Am I missing something?

Michael
 
S

Shawn Hogan

This class seems to do what you want when i run it with your desired code. I
ran with option strict on and it didn't need any ctype's in the client code.
Hope this helps...
Public Class DogCollection
Inherits CollectionBase
Private _keyCollection As New Collections.SortedList
Default Public Property Item(ByVal index As Integer) As dog
Get
Return CType(List.Item(index), dog)
End Get
Set(ByVal Value As dog)
Dim item As dog = CType(List.Item(index), dog)
Dim itemKey As String =
DirectCast(_keyCollection.GetKey(_keyCollection.IndexOfValue(item)), String)
_keyCollection.Item(itemKey) = Value
List.Item(index) = Value
End Set
End Property
Default Public Property Item(ByVal key As String) As dog
Get
Return CType(_keyCollection.Item(key), dog)
End Get
Set(ByVal Value As dog)
Dim item As dog = CType(_keyCollection.Item(key), dog)
Dim itemIndex As Integer = list.IndexOf(item)
list.Item(itemIndex) = Value
_keyCollection.Item(key) = Value
End Set
End Property
Public Sub Add(ByVal key As String, ByVal newItem As dog)
list.Add(newItem)
_keyCollection.Add(key, newItem)
End Sub
Public Sub Remove(ByVal key As String)
Dim item As dog = CType(_keyCollection.Item(key), dog)
list.Remove(item)
End Sub
Protected Overrides Sub OnClearComplete()
_keyCollection.Clear()
End Sub
Protected Overrides Sub OnRemoveComplete(ByVal index As Integer, ByVal value
As Object)
_keyCollection.Remove(_keyCollection.GetKey(_keyCollection.IndexOfValue(valu
e)))
End Sub
End Class
Shawn
 
M

Michael K. Walter

Shawn,

I created a console app/test harness for this and it works fine...thank you.

Now I have to go back to my actual app, conpare and see where I went wrong
(I'm not really dealing with dogs and kennels - as you may have already
guessed).

Thanks again!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top