ArrayList Strongly Typed

G

Guest

I use the following code for a strongly typed arraylist and it works great.
However, I was wondering if this is the proper way to do it. I realize that
if I want to implement sorting of the arraylist then I have to handle this
with a sort method that uses comparer. I can reference the properties of the
Arraylist directly such as

dim mylist as new FrameList
mylist.Add(new FrameStructure)
mylist(0).first = "blabla..."
mylist(0).second = "bla2 bla2..."

'Strongly typed arraylist class "FrameList"
Friend Class FrameList
Inherits ArrayList
Default Public Shadows Property Item(ByVal Index As Integer) As
FrameStructure
Get
Return DirectCast(MyBase.Item(Index), FrameStructure)
End Get
Set(ByVal Value As FrameStructure)
MyBase.Item(Index) = Value
End Set
End Property
End Class
public class FrameStructure
public first as string
public second as string
end class
 
J

J L

Hi Dennis,
I am a .Net newbie so let me ask...why go to the trouble of creating
the FrameList class? Wouldn't this work

Public Class FrameStructure
Public first as string
Public second as string
End Class

Dim myList As New ArrayList
Dim myFrameStructure As New FrameStructure

myFrameStructure.first = "blablabla"
myFrameStructure.second = "bla2bla2bla2"
myList.Add(myFrameStructure)

To use it:

myFrameStructure = ctype(myList(0), FrameStructure)
with myFrameStructure
messagebox.show(.first & vbcrlf & .second)
end with

Am I missing something about strong typing or what?
John
 
D

David

Hi Dennis,
I am a .Net newbie so let me ask...why go to the trouble of creating
the FrameList class? Wouldn't this work

It would work, but...
myFrameStructure = ctype(myList(0), FrameStructure)
with myFrameStructure
messagebox.show(.first & vbcrlf & .second)
end with

Am I missing something about strong typing or what?

Yes, you are. The line
myFrameStructure = ctype(myList(0), FrameStructure)

isn't strongly typed. If you accidently add something other than a
FrameStructure to myList, you won't know about it until runtime when the
CType fails. A strongly-typed list would prevent me from doing that in
the first place.

Converting runtime errors into compile-time errors is what strong typing
is all about.
 
H

Herfried K. Wagner [MVP]

Dennis said:
I use the following code for a strongly typed arraylist and it works great.
However, I was wondering if this is the proper way to do it. I realize
that
if I want to implement sorting of the arraylist then I have to handle this
with a sort method that uses comparer.

You may want to translate the code produced by the collection generator
below to VB.NET:

<URL:http://www.sellsbrothers.com/tools/#collectionGen>

Converting code between .NET programming languages
<URL:http://dotnet.mvps.org/dotnet/faqs/?id=languageconverters&lang=en>
 
J

Jay B. Harlow [MVP - Outlook]

Dennis,
In addition to the other comments, I normally inherit from CollectionBase
when I need a strongly typed arraylist. I normally inherit from
DictionaryBase when I need a strongly typed HashTable.

Something like:

Friend Class FrameList
Inherits CollectionBase

Public Sub Add(ByVal value As FrameStructure)
MyBase.InnerList.Add(value)
End Sub

Default Public Property Item(ByVal Index As Integer) As FrameStructure
Get
Return DirectCast(MyBase.InnerList(Index), FrameStructure)
End Get
Set(ByVal Value As FrameStructure)
MyBase.InnerList(Index) = Value
End Set
End Property

End Class

This allows adding strongly typed methods, such as Add, to the FrameList
also.

Hope this helps
Jay
 
J

Jay B. Harlow [MVP - Outlook]

John,
The following was originally posted by me 23 August 2003 under the
"ArrayList ToArray issues" thread in this newsgroup.

Attached are extended CollectionBase & DictonaryBase classes, that should do
what you want.

I wrote them to mimic CollectionBase & DictionaryBase as close as possible.
The differences being is they have a constructor that you can pass the inner
container to the constructor. And the InnerList changed to an IList type,
while InnerHashtable changed to InnerDictionary of type IDictionary.

CollectionBaseEx accepts an IList in the constructor, if you do not give
one, ArrayList is used. For example you could pass an array of objects,
making a fixed size list, instead of an ArrayList. InnerList does not do
validation, List does validation.

DictionaryBaseEx accepts an IDictionary in the constructor, if you do not
give one, HashTable is used. For example you can pass SortedList,
HybridDictionary, ListDictionary, instead of a HashTable. InnerDictionary
does not do validation, Dictionary does validation.

You can derive from DictionaryBaseEx then pass a new SortedList to the
constructor.

Something like:
Public Class FrameSortedList
Inherits ExDictionaryBase

Public Sub New()
MyBase.New(New SortedList)
End Sub

' other methods you want

End Class

FWIW: I actually started with the m_dictionary field in DictionaryBaseEx as
type SortedList, but then noticed I did not rely on it specifically being a
SortedList, so I modified DictionaryBaseEx to support any IDictionary,
which IMHO actually makes the class far more flexible.

If you use them, let me know if you find any problems with them.

Hope this helps
Jay

---x--- Begin DictionaryBaseEx.vb ---x---
<Serializable()> _
Public MustInherit Class DictionaryBaseEx
Implements IDictionary

Private ReadOnly m_dictionary As IDictionary

Protected Sub New()
MyClass.New(New Hashtable)
End Sub

Protected Sub New(ByVal dictionary As IDictionary)
If dictionary Is Nothing Then
Throw New ArgumentNullException("dictionary")
End If
m_dictionary = dictionary
End Sub

Protected ReadOnly Property InnerDictionary() As IDictionary
Get
Return m_dictionary
End Get
End Property

Protected ReadOnly Property Dictionary() As IDictionary
Get
Return Me
End Get
End Property

Public ReadOnly Property Count() As Integer Implements ICollection.Count
Get
Return m_dictionary.Count
End Get
End Property

Public Sub Clear() Implements IDictionary.Clear
Me.OnClear()
m_dictionary.Clear()
Me.OnClearComplete()
End Sub

Public Sub CopyTo(ByVal array As System.Array, ByVal index As Integer)
Implements ICollection.CopyTo
m_dictionary.CopyTo(array, index)
End Sub

Public Function GetEnumerator() As IDictionaryEnumerator Implements
IDictionary.GetEnumerator
Return m_dictionary.GetEnumerator
End Function

#Region " IDictionary support "

Private ReadOnly Property IDictionary_IsSynchronized() As Boolean
Implements ICollection.IsSynchronized
Get
Return m_dictionary.IsSynchronized
End Get
End Property

Private ReadOnly Property IDictionary_SyncRoot() As Object Implements
ICollection.SyncRoot
Get
Return m_dictionary.SyncRoot
End Get
End Property

Private Function IEnumerable_GetEnumerator() As IEnumerator Implements
IEnumerable.GetEnumerator
Return m_dictionary.GetEnumerator()
End Function

Private Sub IDictionary_Add(ByVal key As Object, ByVal value As Object)
Implements IDictionary.Add
Me.OnValidate(key, value)
Me.OnInsert(key, value)
m_dictionary.Add(key, value)
Me.OnInsertComplete(key, value)
End Sub

Private Function IDictionary_Contains(ByVal key As Object) As Boolean
Implements IDictionary.Contains
Return m_dictionary.Contains(key)
End Function

Private ReadOnly Property IDictionary_IsFixedSize() As Boolean
Implements IDictionary.IsFixedSize
Get
Return m_dictionary.IsFixedSize
End Get
End Property

Private ReadOnly Property IDictionary_IsReadOnly() As Boolean Implements
IDictionary.IsReadOnly
Get
Return m_dictionary.IsReadOnly
End Get
End Property

Private Property IDictionary_Item(ByVal key As Object) As Object
Implements IDictionary.Item
Get
Dim currentValue As Object = m_dictionary.Item(key)
currentValue = Me.OnGet(key, currentValue)
Return currentValue
End Get
Set(ByVal value As Object)
Dim oldValue As Object = m_dictionary.Item(key)
Me.OnValidate(key, value)
Me.OnSet(key, oldValue, value)
m_dictionary.Item(key) = value
Me.OnSetComplete(key, oldValue, value)
End Set
End Property

Private ReadOnly Property IDictionary_Keys() As ICollection Implements
IDictionary.Keys
Get
Return m_dictionary.Keys
End Get
End Property

Private Sub IDictionary_Remove(ByVal key As Object) Implements
IDictionary.Remove
Dim value As Object = m_dictionary.Item(key)
Me.OnValidate(key, value)
Me.OnRemove(key, value)
m_dictionary.Remove(key)
Me.OnRemoveComplete(key, value)
End Sub

Private ReadOnly Property IDictionary_Values() As ICollection Implements
IDictionary.Values
Get
Return m_dictionary.Values
End Get
End Property

#End Region

#Region " Custom processing support "

Protected Overridable Sub OnClear()

End Sub

Protected Overridable Sub OnClearComplete()

End Sub

Protected Overridable Function OnGet(ByVal key As Object, ByVal
currentValue As Object) As Object
Return currentValue
End Function

Protected Overridable Sub OnInsert(ByVal key As Object, ByVal value As
Object)

End Sub

Protected Overridable Sub OnInsertComplete(ByVal key As Object, ByVal
value As Object)

End Sub

Protected Overridable Sub OnRemove(ByVal key As Object, ByVal value As
Object)

End Sub

Protected Overridable Sub OnRemoveComplete(ByVal key As Object, ByVal
value As Object)

End Sub

Protected Overridable Sub OnSet(ByVal key As Object, ByVal oldValue As
Object, ByVal newValue As Object)

End Sub

Protected Overridable Sub OnSetComplete(ByVal key As Object, ByVal
oldValue As Object, ByVal newValue As Object)

End Sub

Protected Overridable Sub OnValidate(ByVal key As Object, ByVal value As
Object)

End Sub

#End Region

End Class
---x--- End DictionaryBaseEx.vb ---x---

---x--- Begin CollectionBaseEx.vb ---x---

<Serializable()> _
Public MustInherit Class CollectionBaseEx
Implements IList

Private ReadOnly m_list As IList

Protected Sub New()
MyClass.New(New ArrayList)
End Sub

Protected Sub New(ByVal list As IList)
If list Is Nothing Then
Throw New ArgumentNullException("list")
End If
m_list = list
End Sub

Protected ReadOnly Property InnerList() As IList
Get
Return m_list
End Get
End Property

Protected ReadOnly Property List() As IList
Get
Return Me
End Get
End Property

Public ReadOnly Property Count() As Integer Implements ICollection.Count
Get
Return m_list.Count
End Get
End Property

Public Sub Clear() Implements IList.Clear
Me.OnClear()
m_list.Clear()
Me.OnClearComplete()
End Sub

Public Function GetEnumerator() As IEnumerator Implements
IList.GetEnumerator
Return m_list.GetEnumerator
End Function

Public Sub RemoveAt(ByVal index As Integer) Implements IList.RemoveAt
Dim value As Object = m_list(index)
Me.OnValidate(value)
Me.OnRemove(index, value)
m_list.RemoveAt(index)
Me.OnRemoveComplete(index, value)
End Sub

#Region " IList support "

Private ReadOnly Property IList_IsSynchronized() As Boolean Implements
ICollection.IsSynchronized
Get
Return m_list.IsSynchronized
End Get
End Property

Private ReadOnly Property IList_SyncRoot() As Object Implements
ICollection.SyncRoot
Get
Return m_list.SyncRoot
End Get
End Property

Private ReadOnly Property IList_IsFixedSize() As Boolean Implements
IList.IsFixedSize
Get
Return m_list.IsFixedSize
End Get
End Property

Private ReadOnly Property IList_IsReadOnly() As Boolean Implements
IList.IsReadOnly
Get
Return m_list.IsReadOnly
End Get
End Property

Private Function IList_Add(ByVal value As Object) As Integer Implements
IList.Add
Dim index As Integer = m_list.Count
Me.OnValidate(value)
Me.OnInsert(index, value)
Return m_list.Add(value)
Me.OnInsertComplete(index, value)
End Function

Private Sub IList_CopyTo(ByVal array As System.Array, ByVal index As
Integer) Implements ICollection.CopyTo
m_list.CopyTo(array, index)
End Sub

Private Function IList_Contains(ByVal value As Object) As Boolean
Implements IList.Contains
Return m_list.Contains(value)
End Function

Private Function IList_IndexOf(ByVal value As Object) As Integer
Implements IList.IndexOf
Return m_list.IndexOf(value)
End Function

Private Sub IList_Insert(ByVal index As Integer, ByVal value As Object)
Implements IList.Insert
Me.OnValidate(value)
Me.OnInsert(index, value)
m_list.Insert(index, value)
Me.OnInsertComplete(index, value)
End Sub

Private Property IList_Item(ByVal index As Integer) As Object Implements
IList.Item
Get
Dim currentValue As Object = m_list.Item(index)
currentValue = Me.OnGet(index, currentValue)
Return currentValue
End Get
Set(ByVal value As Object)
Dim oldValue As Object = m_list(index)
Me.OnValidate(value)
Me.OnSet(index, oldValue, value)
m_list(index) = value
Me.OnSetComplete(index, oldValue, value)
End Set
End Property

Private Sub IList_Remove(ByVal value As Object) Implements IList.Remove
Dim index As Integer = m_list.IndexOf(value)
Me.OnValidate(value)
Me.OnRemove(index, value)
m_list.Remove(value)
Me.OnRemoveComplete(index, value)
End Sub

#End Region

#Region " Custom processing support "

Protected Overridable Sub OnClear()

End Sub

Protected Overridable Sub OnClearComplete()

End Sub

Protected Overridable Function OnGet(ByVal index As Integer, ByVal
currentValue As Object) As Object
Return currentValue
End Function

Protected Overridable Sub OnInsert(ByVal index As Integer, ByVal value
As Object)

End Sub

Protected Overridable Sub OnInsertComplete(ByVal index As Integer, ByVal
value As Object)

End Sub

Protected Overridable Sub OnRemove(ByVal index As Integer, ByVal value
As Object)

End Sub

Protected Overridable Sub OnRemoveComplete(ByVal index As Integer, ByVal
value As Object)

End Sub

Protected Overridable Sub OnSet(ByVal index As Integer, ByVal oldValue
As Object, ByVal newValue As Object)

End Sub

Protected Overridable Sub OnSetComplete(ByVal index As Integer, ByVal
oldValue As Object, ByVal newValue As Object)

End Sub

Protected Overridable Sub OnValidate(ByVal value As Object)

End Sub

#End Region

End Class
---x--- End CollectionBaseEx.vb ---x---
 
G

Guest

I guess the primary reason that I inheirt from the arraylist is the sort
property. In my real application, I make extensive use of the ArrayList Sort
property in my strongly typed arraylist class using Icomparer. What is the
advantage of using the collectionbase over the arraylist?
 
G

Guest

I make extensive use of the ArrayList Sort property using Icomparer in my
real application and I didn't find that the collectionbase has this property.
What's the real advantage of using collectionbase as opposed to inheriting
from an arraylist?
 
J

J L

Hi Jay,
Thanks for the detail. I will have to digest all of it. I am new to
OOP but find this very powerful and exciting.

I also found this link that was interesting:

http://builder.com.com/5100-6373-1050004.html

John

John,
The following was originally posted by me 23 August 2003 under the
"ArrayList ToArray issues" thread in this newsgroup.

Attached are extended CollectionBase & DictonaryBase classes, that should do
what you want.

I wrote them to mimic CollectionBase & DictionaryBase as close as possible.
The differences being is they have a constructor that you can pass the inner
container to the constructor. And the InnerList changed to an IList type,
while InnerHashtable changed to InnerDictionary of type IDictionary.

CollectionBaseEx accepts an IList in the constructor, if you do not give
one, ArrayList is used. For example you could pass an array of objects,
making a fixed size list, instead of an ArrayList. InnerList does not do
validation, List does validation.

DictionaryBaseEx accepts an IDictionary in the constructor, if you do not
give one, HashTable is used. For example you can pass SortedList,
HybridDictionary, ListDictionary, instead of a HashTable. InnerDictionary
does not do validation, Dictionary does validation.

You can derive from DictionaryBaseEx then pass a new SortedList to the
constructor.

Something like:
Public Class FrameSortedList
Inherits ExDictionaryBase

Public Sub New()
MyBase.New(New SortedList)
End Sub

' other methods you want

End Class

FWIW: I actually started with the m_dictionary field in DictionaryBaseEx as
type SortedList, but then noticed I did not rely on it specifically being a
SortedList, so I modified DictionaryBaseEx to support any IDictionary,
which IMHO actually makes the class far more flexible.

If you use them, let me know if you find any problems with them.

Hope this helps
Jay

---x--- Begin DictionaryBaseEx.vb ---x---
<Serializable()> _
Public MustInherit Class DictionaryBaseEx
Implements IDictionary

Private ReadOnly m_dictionary As IDictionary

Protected Sub New()
MyClass.New(New Hashtable)
End Sub

Protected Sub New(ByVal dictionary As IDictionary)
If dictionary Is Nothing Then
Throw New ArgumentNullException("dictionary")
End If
m_dictionary = dictionary
End Sub

Protected ReadOnly Property InnerDictionary() As IDictionary
Get
Return m_dictionary
End Get
End Property

Protected ReadOnly Property Dictionary() As IDictionary
Get
Return Me
End Get
End Property

Public ReadOnly Property Count() As Integer Implements ICollection.Count
Get
Return m_dictionary.Count
End Get
End Property

Public Sub Clear() Implements IDictionary.Clear
Me.OnClear()
m_dictionary.Clear()
Me.OnClearComplete()
End Sub

Public Sub CopyTo(ByVal array As System.Array, ByVal index As Integer)
Implements ICollection.CopyTo
m_dictionary.CopyTo(array, index)
End Sub

Public Function GetEnumerator() As IDictionaryEnumerator Implements
IDictionary.GetEnumerator
Return m_dictionary.GetEnumerator
End Function

#Region " IDictionary support "

Private ReadOnly Property IDictionary_IsSynchronized() As Boolean
Implements ICollection.IsSynchronized
Get
Return m_dictionary.IsSynchronized
End Get
End Property

Private ReadOnly Property IDictionary_SyncRoot() As Object Implements
ICollection.SyncRoot
Get
Return m_dictionary.SyncRoot
End Get
End Property

Private Function IEnumerable_GetEnumerator() As IEnumerator Implements
IEnumerable.GetEnumerator
Return m_dictionary.GetEnumerator()
End Function

Private Sub IDictionary_Add(ByVal key As Object, ByVal value As Object)
Implements IDictionary.Add
Me.OnValidate(key, value)
Me.OnInsert(key, value)
m_dictionary.Add(key, value)
Me.OnInsertComplete(key, value)
End Sub

Private Function IDictionary_Contains(ByVal key As Object) As Boolean
Implements IDictionary.Contains
Return m_dictionary.Contains(key)
End Function

Private ReadOnly Property IDictionary_IsFixedSize() As Boolean
Implements IDictionary.IsFixedSize
Get
Return m_dictionary.IsFixedSize
End Get
End Property

Private ReadOnly Property IDictionary_IsReadOnly() As Boolean Implements
IDictionary.IsReadOnly
Get
Return m_dictionary.IsReadOnly
End Get
End Property

Private Property IDictionary_Item(ByVal key As Object) As Object
Implements IDictionary.Item
Get
Dim currentValue As Object = m_dictionary.Item(key)
currentValue = Me.OnGet(key, currentValue)
Return currentValue
End Get
Set(ByVal value As Object)
Dim oldValue As Object = m_dictionary.Item(key)
Me.OnValidate(key, value)
Me.OnSet(key, oldValue, value)
m_dictionary.Item(key) = value
Me.OnSetComplete(key, oldValue, value)
End Set
End Property

Private ReadOnly Property IDictionary_Keys() As ICollection Implements
IDictionary.Keys
Get
Return m_dictionary.Keys
End Get
End Property

Private Sub IDictionary_Remove(ByVal key As Object) Implements
IDictionary.Remove
Dim value As Object = m_dictionary.Item(key)
Me.OnValidate(key, value)
Me.OnRemove(key, value)
m_dictionary.Remove(key)
Me.OnRemoveComplete(key, value)
End Sub

Private ReadOnly Property IDictionary_Values() As ICollection Implements
IDictionary.Values
Get
Return m_dictionary.Values
End Get
End Property

#End Region

#Region " Custom processing support "

Protected Overridable Sub OnClear()

End Sub

Protected Overridable Sub OnClearComplete()

End Sub

Protected Overridable Function OnGet(ByVal key As Object, ByVal
currentValue As Object) As Object
Return currentValue
End Function

Protected Overridable Sub OnInsert(ByVal key As Object, ByVal value As
Object)

End Sub

Protected Overridable Sub OnInsertComplete(ByVal key As Object, ByVal
value As Object)

End Sub

Protected Overridable Sub OnRemove(ByVal key As Object, ByVal value As
Object)

End Sub

Protected Overridable Sub OnRemoveComplete(ByVal key As Object, ByVal
value As Object)

End Sub

Protected Overridable Sub OnSet(ByVal key As Object, ByVal oldValue As
Object, ByVal newValue As Object)

End Sub

Protected Overridable Sub OnSetComplete(ByVal key As Object, ByVal
oldValue As Object, ByVal newValue As Object)

End Sub

Protected Overridable Sub OnValidate(ByVal key As Object, ByVal value As
Object)

End Sub

#End Region

End Class
---x--- End DictionaryBaseEx.vb ---x---

---x--- Begin CollectionBaseEx.vb ---x---

<Serializable()> _
Public MustInherit Class CollectionBaseEx
Implements IList

Private ReadOnly m_list As IList

Protected Sub New()
MyClass.New(New ArrayList)
End Sub

Protected Sub New(ByVal list As IList)
If list Is Nothing Then
Throw New ArgumentNullException("list")
End If
m_list = list
End Sub

Protected ReadOnly Property InnerList() As IList
Get
Return m_list
End Get
End Property

Protected ReadOnly Property List() As IList
Get
Return Me
End Get
End Property

Public ReadOnly Property Count() As Integer Implements ICollection.Count
Get
Return m_list.Count
End Get
End Property

Public Sub Clear() Implements IList.Clear
Me.OnClear()
m_list.Clear()
Me.OnClearComplete()
End Sub

Public Function GetEnumerator() As IEnumerator Implements
IList.GetEnumerator
Return m_list.GetEnumerator
End Function

Public Sub RemoveAt(ByVal index As Integer) Implements IList.RemoveAt
Dim value As Object = m_list(index)
Me.OnValidate(value)
Me.OnRemove(index, value)
m_list.RemoveAt(index)
Me.OnRemoveComplete(index, value)
End Sub

#Region " IList support "

Private ReadOnly Property IList_IsSynchronized() As Boolean Implements
ICollection.IsSynchronized
Get
Return m_list.IsSynchronized
End Get
End Property

Private ReadOnly Property IList_SyncRoot() As Object Implements
ICollection.SyncRoot
Get
Return m_list.SyncRoot
End Get
End Property

Private ReadOnly Property IList_IsFixedSize() As Boolean Implements
IList.IsFixedSize
Get
Return m_list.IsFixedSize
End Get
End Property

Private ReadOnly Property IList_IsReadOnly() As Boolean Implements
IList.IsReadOnly
Get
Return m_list.IsReadOnly
End Get
End Property

Private Function IList_Add(ByVal value As Object) As Integer Implements
IList.Add
Dim index As Integer = m_list.Count
Me.OnValidate(value)
Me.OnInsert(index, value)
Return m_list.Add(value)
Me.OnInsertComplete(index, value)
End Function

Private Sub IList_CopyTo(ByVal array As System.Array, ByVal index As
Integer) Implements ICollection.CopyTo
m_list.CopyTo(array, index)
End Sub

Private Function IList_Contains(ByVal value As Object) As Boolean
Implements IList.Contains
Return m_list.Contains(value)
End Function

Private Function IList_IndexOf(ByVal value As Object) As Integer
Implements IList.IndexOf
Return m_list.IndexOf(value)
End Function

Private Sub IList_Insert(ByVal index As Integer, ByVal value As Object)
Implements IList.Insert
Me.OnValidate(value)
Me.OnInsert(index, value)
m_list.Insert(index, value)
Me.OnInsertComplete(index, value)
End Sub

Private Property IList_Item(ByVal index As Integer) As Object Implements
IList.Item
Get
Dim currentValue As Object = m_list.Item(index)
currentValue = Me.OnGet(index, currentValue)
Return currentValue
End Get
Set(ByVal value As Object)
Dim oldValue As Object = m_list(index)
Me.OnValidate(value)
Me.OnSet(index, oldValue, value)
m_list(index) = value
Me.OnSetComplete(index, oldValue, value)
End Set
End Property

Private Sub IList_Remove(ByVal value As Object) Implements IList.Remove
Dim index As Integer = m_list.IndexOf(value)
Me.OnValidate(value)
Me.OnRemove(index, value)
m_list.Remove(value)
Me.OnRemoveComplete(index, value)
End Sub

#End Region

#Region " Custom processing support "

Protected Overridable Sub OnClear()

End Sub

Protected Overridable Sub OnClearComplete()

End Sub

Protected Overridable Function OnGet(ByVal index As Integer, ByVal
currentValue As Object) As Object
Return currentValue
End Function

Protected Overridable Sub OnInsert(ByVal index As Integer, ByVal value
As Object)

End Sub

Protected Overridable Sub OnInsertComplete(ByVal index As Integer, ByVal
value As Object)

End Sub

Protected Overridable Sub OnRemove(ByVal index As Integer, ByVal value
As Object)

End Sub

Protected Overridable Sub OnRemoveComplete(ByVal index As Integer, ByVal
value As Object)

End Sub

Protected Overridable Sub OnSet(ByVal index As Integer, ByVal oldValue
As Object, ByVal newValue As Object)

End Sub

Protected Overridable Sub OnSetComplete(ByVal index As Integer, ByVal
oldValue As Object, ByVal newValue As Object)

End Sub

Protected Overridable Sub OnValidate(ByVal value As Object)

End Sub

#End Region

End Class
---x--- End CollectionBaseEx.vb ---x---
 
C

Cor Ligthert

Dennis,
I guess the primary reason that I inheirt from the arraylist is the sort
property. In my real application, I make extensive use of the ArrayList
Sort
property in my strongly typed arraylist class using Icomparer. What is
the
advantage of using the collectionbase over the arraylist?
In my opinion you get a nicer class (with more control from your own and not
in fact strange references). By including Icomparable wherefore are a lot of
samples as well (I thought in combination with this collection.base) you are
able to sort as well.

However just my opinion.

Cor
 
J

Jay B. Harlow [MVP - Outlook]

Dennis,
What is the
advantage of using the collectionbase over the arraylist?
As I stated CollectionBase allows you to define Strongly Typed collections!

Ones that are Option Strict On friendly & OO friendly. When you inherit from
ArrayList, you need to use Shadows to replace the Add method with a type
safe Add. Using Shadows is anti-polymorphoric. Remember that polymorphism is
one of the major tenents of OO. You need to use Overrides not Shadows to
create polymorphoric methods in relation to the base type...

Consider the following using your original post:
Friend Class FrameList
Inherits ArrayList
Public Shadows Sub Add(value As FrameStructure)
MyBase.Add(value)
End Sub
Default Public Shadows Property Item(ByVal Index As Integer) As
FrameStructure

I can define an ArrayList variable that holds a FrameList

Dim list As ArrayList = New FrameList

Because of the Shadows I can add a string to the FrameList.

list.Add("Hello World")

This will cause untold problems in your indexer (Item property) & any For
Each loops.

Shadows is primarily intended for Version control & not designing new
classes. For example you inherit from Control & define a Widget property,
version 2.0 of the class library ships with a Control.Widget property which
is incompatible with your Widget property. Shadows allows you to continue to
use your Widget property & Control to continue to use its. As time becomes
available you would need to change the name of your Widget property...

When you inherit from CollectionBase the actual ArrayList is not exposed.
Meaning you cannot cast your FrameList into an ArrayList. CollectionBase
does support the IList interface for polymorphism. If your solution
leverages this functionality then its a good idea to override the
CollectionBase.On* methods (such as OnValidate) to ensure that the objects
being added to your collection are of the correct type.

Friend Class FrameList
Inherits CollectionBase

Public Sub Add(ByVal value As FrameStructure)
MyBase.InnerList.Add(value)
End Sub

Default Public Property Item(ByVal Index As Integer) As FrameStructure
Get
Return DirectCast(MyBase.InnerList(Index), FrameStructure)
End Get
Set(ByVal Value As FrameStructure)
MyBase.InnerList(Index) = Value
End Set
End Property

Protected Overrides Sub OnValidate(ByVal value As Object)
If Not TypeOf value Is FrameStructure Then
Throw New InvalidCastException
End If
End Sub

End Class

I make extensive use of the ArrayList Sort
property in my strongly typed arraylist class using Icomparer.
CollectionBase exposes the contained ArrayList as InnerList your custom
class can sort based on InnerList.Sort.

Hope this helps
Jay
 
A

Alejandro Lapeyre

Why bother inheriting from CollectionBase?

Just implement the interfaces (IList and others as needed) and your save
yourself one wrapper.

Best Regards,
Alejandro Lapeyre
 
A

Alejandro Lapeyre

Why bother inheriting from CollectionBase?

Just implement IList (and other interfaces as needed) and you save yourself
one wrapper.

Best Regards,
Alejandro Lapeyre
 
D

David

Why bother inheriting from CollectionBase?

Just implement the interfaces (IList and others as needed) and your save
yourself one wrapper.

I'm of two minds here...


On the one hand, CollectionBase is already there, it's already debugged
and working and reasonably optimized, and it does almost exactly what
you'd have to do yourself if you wanted to roll your own class.

In most cases rolling your own isn't going to gain you much. You still
have to wrap a list of some kind, so the indirection is still there.
Granted, you could take over autosizing by keeping an array and resizing
it as needed, but I'd want to see real problems come out of the profiler
before I assigned *that* to somebody. The one time I could see an
advantage to doing this is if I were doing massive thrashing of value
type collections.

On the other hand, CollectionBase is a huge hole in the type system
since you can't get typed enumerations out of it (if there's a way to do
this, somebody correct me please, it's been quite a while since I looked
at it.) At one point I convinced myself that this was such a huge
annoyance that I was going to upgrade all my collection templates, but I
never did it, and I've never had an enumeration type bug that would have
forced the issue. So maybe it's not a big deal.
 
J

Jay B. Harlow [MVP - Outlook]

David,
On the other hand, CollectionBase is a huge hole in the type system
since you can't get typed enumerations out of it
What do you mean by "typed enumerations"? I have not any problems with
putting Enums into a CollectionBase, nor have I had any problems with the
implementation if CollectionBase.GetEnumerator!

Were you attempting to replace (Shadow) CollectionBase.GetEnumerator?

What specifically are you expecting in a "typed enumerations"?

Hope this helps
Jay
 
J

Jay B. Harlow [MVP - Outlook]

Alejandro,
Why bother inheriting from CollectionBase?
To avoid a lot of duplication of code! Instead I prefer to let most if not
all that duplicate code reside in a single base class CollectionBase.

Duplication of code is one code smell I can do without!
Just implement the interfaces (IList and others as needed) and your save
yourself one wrapper.
The primary reason I would consider avoiding the wrapper would be if
profiling showed that the wrapper was a performance problem! The secondary
reason I would consider avoiding the wrapper would be if I was defining a
collection of value types, that was expected to be used heavily, so as to
avoid the boxing penalty. Of course (the current) IList interface would
continue to have the boxing penalty!

Just Remember the 80/20 rule. That is 80% of the execution time of your
program is spent in 20% of your code. I will optimize (worry about
performance, memory consumption) the 20% once that 20% has been identified &
proven to be a performance problem via profiling (CLR Profiler is one
profiling tool).

For info on the 80/20 rule & optimizing only the 20% see Martin Fowler's
article "Yet Another Optimization Article" at
http://martinfowler.com/ieeeSoftware/yetOptimization.pdf

Info on the CLR Profiler:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenethowto13.asp

http://msdn.microsoft.com/library/d...y/en-us/dndotnet/html/highperfmanagedapps.asp

Hope this helps
Jay
 
D

David

David,
What do you mean by "typed enumerations"?

Strong typing in a For Each enumeration.


I have not any problems with
putting Enums into a CollectionBase, nor have I had any problems with the
implementation if CollectionBase.GetEnumerator!

Were you attempting to replace (Shadow) CollectionBase.GetEnumerator?

What specifically are you expecting in a "typed enumerations"?

A virtual (overridable) GetEnumerator of some type, I suppose.
"Expecting" is definitely the wrong term there, BTW, I understand why
this can't be.

Like I said, in practice it seems I don't really care all that much.
Shadowing achieves most of what I want with enumerations. Still, a
roll-your-own implementation wouldn't have all those untyped accessors
built in. And I'm not entirely sure it's accurate to call something
strongly typed if you can break the type system without casting, the way
you can with CollectionBase.

At one point, I thought this would really bother me. It turns out it
didn't, and pretty much all my typed collections right now use
CollectionBase. I'm not 100% sure I made the right decision, but it's
not something I think about very much, so I guess I'm happy with the
choice.
 
J

Jay B. Harlow [MVP - Outlook]

David,
Strong typing in a For Each enumeration.

Can you define & give a VB example of "every day" needing strong typing in a
For Each enumeration. I can think of one example, however its a
performance/boxing thing which is needed in less then 20% of my code...

A virtual (overridable) GetEnumerator of some type, I suppose.
"Expecting" is definitely the wrong term there, BTW, I understand why
this can't be.
How do you see an overridable GetEnumerator providing strong typing? Based
on the performance/boxing requirement I can see an explicit interface
implementation & a strongly typed Enumerator class, again less then 20% of
my code (in fact I have yet to need this optimization).

Going back to your original post:
I am trying to figure out what & how this "huge hole in the type system" you
perceive is, so that possible I or someone else can correct you. As quite
truthfully I don't see any real holes in CollectionBase, especially when you
overload the CollectionBase.On* methods. Granted you may have runtime errors
as opposed to compile time errors, however you run that risk (runtime
errors) when using generalized interfaces as IList in any class that
implements IList.


Hope this helps
Jay
 

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