Results 1 to 13 of 13

Thread: [RESOLVED] Collection-like solution with both strong typing and keys

  1. #1

    Thread Starter
    New Member
    Join Date
    Jun 2015
    Posts
    6

    Resolved [RESOLVED] Collection-like solution with both strong typing and keys

    I'm trying to find a suitable solution for a collection of objects I have in Visual Basic. I would like the solution to have two properties:
    1. Strong typing
    2. Key-based access (in addition to index-based access)

    So far I've been able to find structures that have one or the other. For example, List supports strong typing in its declaration but does not allow element access by key. Meanwhile, Collection elements are key-able but not strongly typed. What is the ideal solution here?

    Thanks!

  2. #2
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    Re: Collection-like solution with both strong typing and keys

    If you want access by key and by index then you can create an object which encapsulates both a list and a dictionary.

    Or, you can use a System.Collections.Specialized.OrderedDictionary. Sounds like it'll do the job.
    "Ok, my response to that is pending a Google search" - Bucky Katt.
    "There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
    "Before you can 'think outside the box' you need to understand where the box is."

  3. #3

    Thread Starter
    New Member
    Join Date
    Jun 2015
    Posts
    6

    Re: Collection-like solution with both strong typing and keys

    Quote Originally Posted by SJWhiteley View Post
    If you want access by key and by index then you can create an object which encapsulates both a list and a dictionary.

    Or, you can use a System.Collections.Specialized.OrderedDictionary. Sounds like it'll do the job.
    Well, I can definitely find a structure that allows access by both key and index (even a simple Collection does this). The issue I'm having is that those types, as far as I've seen, do not support strong typing. The OrderedDictionary, for example, doesn't take in an object type when it is initialized (as arrays and Lists do), so there's no way (that I'm aware of) to check that only objects of a particular type can be inside at compile time.

  4. #4
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    Re: Collection-like solution with both strong typing and keys

    Well, if the OrderedDictionary (I had thought that it did) doesn't have strong typing, then just create an object encapsulating a List and Dictionary, and add methods to get items by index or key, as appropriate.

    Edit: it also sounds like you may be talking about the specific Microsoft.Visualbasic.Collection object, rather than the strongly typed, generic, collections available in the .NET framework: you should never be using that for anything.
    Last edited by SJWhiteley; Jul 6th, 2015 at 11:23 AM.
    "Ok, my response to that is pending a Google search" - Bucky Katt.
    "There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
    "Before you can 'think outside the box' you need to understand where the box is."

  5. #5
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,988

    Re: Collection-like solution with both strong typing and keys

    Hunh, I had never heard of an OrderedDictionary. That one doesn't appear to be strongly typed, but the Dictionary is, as is the SortedDictionary:

    https://msdn.microsoft.com/en-us/lib...v=vs.110).aspx

    You can also use indexes with Dictionaries, so you don't need both a list and dictionary to get all your requirements met.
    My usual boring signature: Nothing

  6. #6
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    Re: Collection-like solution with both strong typing and keys

    SortedDictionary sorts on the key, which may or may not provide the 'index' you want. I had presumed that an index-based collection would be indexed by the order they are added to the collection. Something that the SortedDictionary and Dictionary do not do.

    (While you can use an iterator or an extension method on a dictionary, I'm not sure that it will give you the order that items are added).
    "Ok, my response to that is pending a Google search" - Bucky Katt.
    "There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
    "Before you can 'think outside the box' you need to understand where the box is."

  7. #7
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,531

    Re: Collection-like solution with both strong typing and keys

    well, it seems you get one or the other.... strongly typed objects, OR you get key/index access... I was able to get this working:

    Code:
            Dim openWith As New Dictionary(Of String, String)
    
            ' Add some elements to the dictionary. There are no  
            ' duplicate keys, but some of the values are duplicates.
            openWith.Add("txt", "notepad.exe")
            openWith.Add("bmp", "paint.exe")
            openWith.Add("dib", "paint.exe")
            openWith.Add("rtf", "wordpad.exe")
    
    
            MessageBox.Show(openWith.Item(openWith.Keys(1)))
    The index is passed to the Keys collection, which then returns the key for that index, which is then passed to the Item collection and returns the value - "paint.exe" in this case.
    You could probably roll your own class that acts like a Dictionary but overloads the Items property to accept a Key (as String) or an Index (as Integer).


    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  8. #8

    Thread Starter
    New Member
    Join Date
    Jun 2015
    Posts
    6

    Re: Collection-like solution with both strong typing and keys

    Quote Originally Posted by SJWhiteley View Post
    SortedDictionary sorts on the key, which may or may not provide the 'index' you want. I had presumed that an index-based collection would be indexed by the order they are added to the collection. Something that the SortedDictionary and Dictionary do not do.

    (While you can use an iterator or an extension method on a dictionary, I'm not sure that it will give you the order that items are added).
    I initially thought that a SortedDictionary would do the trick, but you're correct in that the indexing order is not what I want. For now, I'll take your suggestion and create my own solution. I'd still love to hear about any built-in types that support what I'm trying to accomplish--it seems like one should exist, unless my need is a lot more specific than I imagine it to be. If no more suggestions crop up within a few hours, I'll mark this thread as resolved. Thanks!

  9. #9
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,531

    Re: Collection-like solution with both strong typing and keys

    Here's something to help you get started with.... I implemented the IDictionary(Of) interface... made some modifications where needed.
    Code:
    Public Class CustomKeyIndex(Of TKey, TValue)
        Implements IDictionary(Of TKey, TValue)
    
        Private _internalDictionary As New Dictionary(Of TKey, TValue)
        Private _isreadOnly As Boolean = False
    
        Public Sub Add(item As KeyValuePair(Of TKey, TValue)) Implements ICollection(Of KeyValuePair(Of TKey, TValue)).Add
            _internalDictionary.Add(item.Key, item.Value)
        End Sub
    
        Public Sub Clear() Implements ICollection(Of KeyValuePair(Of TKey, TValue)).Clear
            _internalDictionary.Clear()
        End Sub
    
        Public Function Contains(item As KeyValuePair(Of TKey, TValue)) As Boolean Implements ICollection(Of KeyValuePair(Of TKey, TValue)).Contains
            Return _internalDictionary.Contains(item)
        End Function
    
        Public Sub CopyTo(array() As KeyValuePair(Of TKey, TValue), arrayIndex As Integer) Implements ICollection(Of KeyValuePair(Of TKey, TValue)).CopyTo
            array = _internalDictionary.ToArray
        End Sub
    
        Public ReadOnly Property Count As Integer Implements ICollection(Of KeyValuePair(Of TKey, TValue)).Count
            Get
                Return _internalDictionary.Count
            End Get
        End Property
    
        Public ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of KeyValuePair(Of TKey, TValue)).IsReadOnly
            Get
                Return _isreadOnly
            End Get
        End Property
    
        Public Function Remove(item As KeyValuePair(Of TKey, TValue)) As Boolean Implements ICollection(Of KeyValuePair(Of TKey, TValue)).Remove
            _internalDictionary.Remove(item.Key)
        End Function
    
        Public Sub Add(key As TKey, value As TValue) Implements IDictionary(Of TKey, TValue).Add
            _internalDictionary.Add(key, value)
        End Sub
    
        Public Function ContainsKey(key As TKey) As Boolean Implements IDictionary(Of TKey, TValue).ContainsKey
            Return _internalDictionary.ContainsKey(key)
        End Function
    
        Default Public Property Item(key As TKey) As TValue Implements IDictionary(Of TKey, TValue).Item
            Get
                Return _internalDictionary(key)
            End Get
            Set(value As TValue)
                _internalDictionary(key) = value
            End Set
        End Property
    
        Default Public Property Item(index As Integer) As TValue
            Get
                Return _internalDictionary(_internalDictionary.Keys(index))
            End Get
            Set(value As TValue)
                _internalDictionary(_internalDictionary.Keys(index)) = value
            End Set
        End Property
    
        Public ReadOnly Property Keys As ICollection(Of TKey) Implements IDictionary(Of TKey, TValue).Keys
            Get
                Return _internalDictionary.Keys
            End Get
        End Property
    
        Public Function Remove1(key As TKey) As Boolean Implements IDictionary(Of TKey, TValue).Remove
            _internalDictionary.Remove(key)
        End Function
    
        Public Function TryGetValue(key As TKey, ByRef value As TValue) As Boolean Implements IDictionary(Of TKey, TValue).TryGetValue
            Dim retValue As Boolean = False
    
            If _internalDictionary.Keys.Contains(key) Then
                value = _internalDictionary.Item(key)
                retValue = True
            End If
    
            Return retValue
    
        End Function
    
        Public ReadOnly Property Values As ICollection(Of TValue) Implements IDictionary(Of TKey, TValue).Values
            Get
                Return _internalDictionary.Values
            End Get
        End Property
    
        Public Function GetEnumerator() As IEnumerator(Of KeyValuePair(Of TKey, TValue)) Implements IEnumerable(Of KeyValuePair(Of TKey, TValue)).GetEnumerator
            Return _internalDictionary.GetEnumerator
        End Function
    
        Public Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator
            Return _internalDictionary.GetEnumerator
        End Function
    End Class
    I can then access the elements via Key or Index:
    Code:
            Dim openWithCustom As New CustomKeyIndex(Of String, String)
    
            openWithCustom.Add("txt", "notepad.exe")
            openWithCustom.Add("bmp", "paint.exe")
            openWithCustom.Add("dib", "paint.exe")
            openWithCustom.Add("rtf", "wordpad.exe")
    
            MessageBox.Show(openWithCustom.Item(3))
            MessageBox.Show(openWithCustom.Item("txt"))
    -tg

    addendum: I'll admit though, it seems a bit hackish... there's probably a better way to go about it.
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  10. #10
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    Re: Collection-like solution with both strong typing and keys

    I had created my own class which implements an IDictionary and IList, which contains both a list and a Dictionary object. Simply, when you add and remove objects, you add and remove from both the dictionary and the list. When you reference by index then look at the List, by key, look at the Dictionary.
    "Ok, my response to that is pending a Google search" - Bucky Katt.
    "There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
    "Before you can 'think outside the box' you need to understand where the box is."

  11. #11
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,531

    Re: Collection-like solution with both strong typing and keys

    That seems a bit more brute-forcish especally when having to maintain both a list and dictionary. That's just my opinion though. I've seen others do that too. It just seems easier to overload the dictionary's .Item method to also accept an index... I guess in the end, it doesn't matter as the result is the same.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  12. #12
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,531

    Re: Collection-like solution with both strong typing and keys

    Actually... I'm curious as to how you handle some of the List methods, particularly the .Add ... how does the value get added to the Dictionary?

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  13. #13
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    Re: Collection-like solution with both strong typing and keys

    When you add an item, you need a key. Just like any other dictionary object. The list actually is a list of Key Value Pairs (I created my own object), so you can cross-reference from List to Dictionary and visa versa. Removing objects is a little tricky, but not overly so.

    Regarding brute force: the dictionary index isn't necessarily the index an item was added. I'm not sure how you would override the Item method. Likewise, how do you 'add' at a specific index, since it doesn't appear a dictionary has those mechanisms.
    "Ok, my response to that is pending a Google search" - Bucky Katt.
    "There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
    "Before you can 'think outside the box' you need to understand where the box is."

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width