Home All Groups Group Topic Archive Search About

Problem when iterating through custom dictionary based collection with FOR...EACH...NEXT

Author
24 Jan 2006 8:40 AM
Martin Widmer
Hi Folks.

When I iterate through my custom designed collection, I always get the
error:

"Unable to cast object of type 'System.Collections.DictionaryEntry' to type
'ContentObjects.ContentBlock'."

The error occurs at the "For...Each" line if this method:

    Public Function GetContentBlock(ByVal nDBKey As Long) As ContentBlock
        Dim oContentBlock As ContentBlock

        For Each oContentBlock In Me.ContentBlocks
            If oContentBlock.DBKey = nDBKey Then
                Return oContentBlock
            End If
        Next
        Return Nothing
    End Function

And the collection class is built as follows:

Public Class ContentBlocksCollection
    Inherits DictionaryBase
    'Object variables for attributes
    'Attributes
    Default Public Property Item(ByVal nDBKey As Long) As ContentBlock
        Get
            Return MyBase.Dictionary.Item(nDBKey)
        End Get
        Set(ByVal value As ContentBlock)
            MyBase.Dictionary.Item(nDBKey) = value
        End Set
    End Property
    'Methods
    Public Sub Add(ByVal oContentBlock As ContentBlock)
        MyBase.Dictionary.Add(oContentBlock.DBKey, oContentBlock)
    End Sub
    Public Sub Remove(ByVal nDBKey As Long)
        MyBase.Dictionary.Remove(nDBKey)
    End Sub
    Public Function Contains(ByVal nDBKey As Long) As Boolean
        Return MyBase.Dictionary.Contains(nDBKey)
    End Function
End Class

What am I doing wrong?

Martin

Author
24 Jan 2006 2:09 PM
Larry Lard
Martin Widmer wrote:
> Hi Folks.
>
> When I iterate through my custom designed collection, I always get the
> error:
>
> "Unable to cast object of type 'System.Collections.DictionaryEntry' to type
> 'ContentObjects.ContentBlock'."
>
> The error occurs at the "For...Each" line if this method:

When you For Each over a dictionary, what you are enumerating are not
the values, nor the keys, but the dictionary entries - each of which is
a key-value pair. To be specifc, quoting the docs for DictionaryBase:

The [For Each statement] requires the type of each element in the
collection. Since each element of the DictionaryBase is a key-and-value
pair, the element type is not the type of the key or the type of the
value. Instead, the element type is DictionaryEntry. For example:

[Visual Basic]
Dim myDE As DictionaryEntry
For Each myDE In myDictionary
   ...
Next myDE

>     Public Function GetContentBlock(ByVal nDBKey As Long) As ContentBlock
>         Dim oContentBlock As ContentBlock
>
>         For Each oContentBlock In Me.ContentBlocks
>             If oContentBlock.DBKey = nDBKey Then
>                 Return oContentBlock
>             End If
>         Next
>         Return Nothing
>     End Function

I should say that here you appear to be duplicating the existing
functionality of the DictionaryBase - the point of a dictionary is to
be able to retrieve values given keys. Why can't you just say
ContentBlocks(nDBKey) ?

> And the collection class is built as follows:
>
> Public Class ContentBlocksCollection
>     Inherits DictionaryBase
>     'Object variables for attributes
>     'Attributes
>     Default Public Property Item(ByVal nDBKey As Long) As ContentBlock
>         Get
>             Return MyBase.Dictionary.Item(nDBKey)

This suggests you're running without Option Strict On. It's generally
recommended that Option Strict should always be On - the additional
typing sometimes required is more than outweighted by the strict type
safety granted.

Show quoteHide quote
>         End Get
>         Set(ByVal value As ContentBlock)
>             MyBase.Dictionary.Item(nDBKey) = value
>         End Set
>     End Property
>     'Methods
>     Public Sub Add(ByVal oContentBlock As ContentBlock)
>         MyBase.Dictionary.Add(oContentBlock.DBKey, oContentBlock)
>     End Sub
>     Public Sub Remove(ByVal nDBKey As Long)
>         MyBase.Dictionary.Remove(nDBKey)
>     End Sub
>     Public Function Contains(ByVal nDBKey As Long) As Boolean
>         Return MyBase.Dictionary.Contains(nDBKey)
>     End Function
> End Class

I'm not sure what all the .Dictionary references add: you might just as
well say MyBase.Item, MyBase.Add and so on.

--
Larry Lard
Replies to group please