Karl Stephen
Karl Stephen

Reputation: 1140

Implement a generic Collection of Collections class with two types constrain in dot Net - getting started

I won't elaborate the classes in the four Collections namespaces (System.Collections, Collections.Generic, .Specialized and .Concurrent) but what I need is something like

SortedCollection(Of TKey As IComparable, TValue)

that is obviously a generic, looking identical to SortedList, but, difference with SortedList is, while TValue is declared the same way, SortedList is a KeyPair(TKey, TValue). What we need is TValue being the declared type constrain of a KeyPair(TKey, List(Of TValue))

Here is the concept of this collection :

Key1
 |--Value1
 |--Value2
Key2 (No Values)
Key3
 |--Value3
 |--Value4
 |--Value5
Key4
...

With the common members of a classic generic collection, with custom members like :

GetValue(Key, Index) As TValue
RemoveValueAt(Key, Index) As TValue
ClearCollection(Key)
...

At first glance, the best option is to create a derived class :

Public Class SortedCollection(Of TKey As IComparable, TValue)
    Inherits SortedList(Of TKey, List(Of TValue))
    ...

But no : you can't override the Add() method, that I would like to call on this SortedCollection class the following way :

Dim MyCol As New SortedCollection(Of String, String)()
MyCol.Add("Car", "Ford")
MyCol.Add("Aircraft", "Boeing")
MyCol.Add("Aircraft", "Airbus")
MyCol.Add("Boat", "Aircraft Carrier")
MyCol.Add("Boat", "Aircraft Carrier") '// Doesn't throw Exception !
MyCol.Add("Car", "") '// Doesn't throw Exception !

'// "Aircraft" -> "Boeing", "Airbus"
'// "Car" -> "Ford", ""
'// "Boat" -> "Aircraft Carrier", "Aircraft Carrier"

One may think of using the Shadow (VB) keyword (if that helps) but I would like to avoid it (as someone else in the team may work on the code aswell, and we don't like to disagree about the usage of this or that)

Then, I guess the best option is to create a custom collection class with the appropriate interfaces (IEnumerable, ICollection(Of KeyValuePair), etc.), what I've tried before coming here.

So where to begin with ?

The point of this question is not to discuss about the interfaces that should be used, nor the usage kindof of such collection, but to get started the right way. All documentations I've found are about Collections of objects, but I've found none about collections of collections. Being collections of different types (box/unbox, base/derived, interfaces/implementations), or not actually a collection of collection, but rather a collection of KeyValuePair(TGroup, TValue), none gives a clear picture of a collection with two generic types, the second being the type of an underlying collection.

Especially when implementing the IEnumerable interface : To get started with the correct Enumerator Class, it has to be declared as :

'// iterates all Values through the Keys
SortedCollectionEnumerator(Of TKey, TValue) As IEnumerator ???
SortedCollectionEnumerator(Of TKey, TValue) As IEnumerator(Of TKey) ???
SortedCollectionEnumerator(Of TKey, TValue) As IEnumerator(Of TValue) ???
SortedCollectionEnumerator(Of TKey, TValue) As IEnumerator(Of TKey, TValue) ???

The last one doesn't exist. What to do otherwise. All I've used so far is Enumerator(Of T)


Or should I create everything from scratch (which is what I'm doing at the moment), including the Enumerator (reinvent the wheel ? avoid it as they said...) Will that work ? Or derive from CollectionBase and implement a tons of constrains and checks ?

I don't require Thread Safe; it's not for DataBases or network. DotNet 4.0, 4.5, 4.6 or above, whatever ! VBNet (as required by the project) but C# is welcome (personal preference)

Just the guidelines if you're willing to help, and perhaps a summary of some important points to not underestimate, like Dispose(), deprecated methods/properties to avoid...

Thanks.

Upvotes: 1

Views: 255

Answers (1)

Dejan
Dejan

Reputation: 10323

Instead of deriving from SortedList, wrap a SortedList<TKey, List<TValue>> (i.e. have it as a private field). Then implement whatever interface you need and use the private member internally.

Upvotes: 1

Related Questions