Groups | Blog | Home
all groups > vb.net > january 2005 >

vb.net : Custom collection and For Each


Michael Kellogg
1/29/2005 11:02:29 PM
I created a custom collection based on
System.Collections.Specialized.NameObjectCollectionBase. I also
implemented two version of the "Item" property and coded them both as
Default properties.

Now, when I look at the data, everything looks good; the underlying objects
in there, and the Item property returns the same even if I just access like
this: Label(i), so that is cool.

However, I tried to do a For...Each on the object just now and it's not
returning to me the underlying object (as is specified in the Item
properties). Instead it's returning the string key for that element.

What gives? I want to iterate through the collection with a For...Each but
cannot see what I'm doing wrong.

Appreciate any suggestions.

--
God Bless,
Michael Kellogg
1/30/2005 12:43:14 AM
"Cor Ligthert" <notmyfirstname@planet.nl> wrote (in
microsoft.public.dotnet.languages.vb):

[quoted text, click to view]

Cor,

My, what a tactful guy you are.

Here is part of the collection of my custom object:
------------

Public Class FormLabels
Inherits System.Collections.Specialized.NameObjectCollectionBase

Default Public ReadOnly Property Item(ByVal index As Integer) As
FormLabel
Get
Return BaseGet(index)
End Get
End Property
Default Public ReadOnly Property Item(ByVal FormCode As String) As
FormLabel
Get
Return BaseGet(FormCode)
End Get
End Property
....
End Class

---------
Here is the code where I try to iterate the collection:
---------
Protected Sub RefreshForms()
With lstForms.Items
.Clear()
Dim fl As FormLabel
Dim fls As FormLabels
fls = m_JobLabel.FormLabels 'pass the copy one time
For Each fl In fls
.Add(fl.FormCode + " (" + fl.FormNumber.ToString + ")")
Next
End With
End Sub

------------
As it stands, I get an InvalidCastException at the "For Each" statement.
I went back and changed fl's definition to "Object" and discovered that
it was handed a String (it is the element's key), not a FormLabel object.
What I don't get is what the "Each" clause goes and gets. I assumed it
was the default property, which should return an object to me, not a
string.

I can work around this by iterating the collection manually, but I want
to know how to get the "Each" to work.



Michael Kellogg
1/30/2005 1:47:29 AM
"Cor Ligthert" <notmyfirstname@planet.nl> wrote (in
microsoft.public.dotnet.languages.vb):

[quoted text, click to view]

?

I just supplied you with all the code in question, as you requested.
Didn't you see all that below my initial comments?



Cor Ligthert
1/30/2005 8:58:52 AM
Michael.

Do you want to know what you are doing wrong in the code you did not show?

You see the code before you, how you think anybody can help you when he does
not know what you did. Therefore when you want help, show some code (piece
by piece the first time and first pasted in a noteback an copied back in
your message to make it readable)

Cor

Cor Ligthert
1/30/2005 10:08:41 AM
Michael,

[quoted text, click to view]
Do if I did not ask to show your code.

I am sorry Michael, without your code I cannot help you.

Cor

ABad
1/30/2005 3:05:32 PM
To handle "For Each" a collection must implement IEnumerable.
NameObjectCollectionBase already implements this interface and it looks like
the implementation iterates over the keys.


[quoted text, click to view]

Michael Kellogg
1/31/2005 11:13:01 AM
[quoted text, click to view]

Let me ask this (I'm not familiar with the interfaces and have not found
any decent info about them, like IEnumerable): Let's say this is what is
happening, that the For Each is enumerating the keys. This makes the
iteration through my collection unusual, because I have to then use the
key that is returned to pull up the actual object inside the collection.
In other words:
----------

dim key as string
for each key in MyObjects
MyObjects(key).myProperty = x
next

----------
Is different than this standard implementation:
----------

dim obj as MyObject
for each obj in MyObjects
obj.myProperty = x
next


----------
What I'm trying to understand is how to make it work in the latter case.
My Default property is ITEM, which returns an object (not the key
string). What am I missing?

--
ABad
1/31/2005 3:14:34 PM
[quoted text, click to view]

It is whats happening. I tested it and looked at the IL of the
NameObjectCollectionBase class.

[quoted text, click to view]

Like I said the "For Each" mechanism is dependent on the IEnumerable
interface, NOT Default property. For NameObjectCollectionBase class, the
implementation is enumerate over the keys. You cannot "elegantly" override
this behavior so you can't depend on NameObjectCollectionBase to do what you
want. Now you could "shadow" the GetEnumerator method and provide your own
implementation of IEnumerator but you should read up on what "shadows" does
before you take this step.

What I would do for an "elegant" design is implement my own class that
implements the ICollection interface. Expose all methods necessary and defer
the implementation details to an existing .NET data structure that supplies
the needed functionality, say hashtable. I would then implement IEnumerable
with my own implementation.

- ABad




[quoted text, click to view]

AddThis Social Bookmark Button