Home All Groups Group Topic Archive Search About

ArrayList Strongly Typed

Author
25 Mar 2005 12:57 AM
Dennis
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
--
Dennis in Houston

Author
25 Mar 2005 4:56 AM
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

On Thu, 24 Mar 2005 16:57:02 -0800, Dennis
<Den***@discussions.microsoft.com> wrote:

Show quoteHide quote
>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
Author
25 Mar 2005 8:28 AM
David
On 2005-03-25, J L <j***@marymonte.com> wrote:
> 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.
Author
25 Mar 2005 7:46 AM
Cor Ligthert
Dennis,

Why you inherit from Arraylist and not direct from the collectionbase

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemcollectionscollectionbaseclasstopic.asp

A nice sample is included in that page

In my opinion is that simpler and more consistent.

I hope this helps?

Cor
Author
25 Mar 2005 9:35 PM
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?

Show quoteHide quote
"Cor Ligthert" wrote:

> Dennis,
>
> Why you inherit from Arraylist and not direct from the collectionbase
>
> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemcollectionscollectionbaseclasstopic.asp
>
> A nice sample is included in that page
>
> In my opinion is that simpler and more consistent.
>
> I hope this helps?
>
> Cor
>
>
>
Author
26 Mar 2005 8:17 AM
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
Author
26 Mar 2005 4:42 PM
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

Show quoteHide quote
"Dennis" <Den***@discussions.microsoft.com> wrote in message
news:B5527DF7-A000-4772-8352-6269131CB7DE@microsoft.com...
>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?
>
> "Cor Ligthert" wrote:
>
>> Dennis,
>>
>> Why you inherit from Arraylist and not direct from the collectionbase
>>
>> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemcollectionscollectionbaseclasstopic.asp
>>
>> A nice sample is included in that page
>>
>> In my opinion is that simpler and more consistent.
>>
>> I hope this helps?
>>
>> Cor
>>
>>
>>
Author
26 Mar 2005 5:33 PM
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


Show quoteHide quote
"Jay B. Harlow [MVP - Outlook]" <Jay_Harlow_***@msn.com> escribió en el
mensaje news:OPTMYLiMFHA.3420@tk2msftngp13.phx.gbl...
> 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
>
> "Dennis" <Den***@discussions.microsoft.com> wrote in message
> news:B5527DF7-A000-4772-8352-6269131CB7DE@microsoft.com...
>>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?
>>
>> "Cor Ligthert" wrote:
>>
>>> Dennis,
>>>
>>> Why you inherit from Arraylist and not direct from the collectionbase
>>>
>>> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemcollectionscollectionbaseclasstopic.asp
>>>
>>> A nice sample is included in that page
>>>
>>> In my opinion is that simpler and more consistent.
>>>
>>> I hope this helps?
>>>
>>> Cor
>>>
>>>
>>>
>
>
Author
26 Mar 2005 9:54 PM
David
On 2005-03-26, Alejandro Lapeyre <AlejandroLape***@jotmail.com> wrote:
> 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.
Author
27 Mar 2005 4:58 AM
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

Show quoteHide quote
"David" <dfos***@woofix.local.dom> wrote in message
news:slrnd4b0sq.9am.dfoster@woofix.local.dom...
> On 2005-03-26, Alejandro Lapeyre <AlejandroLape***@jotmail.com> wrote:
>> 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.
>
>
Author
27 Mar 2005 8:46 AM
David
On 2005-03-27, Jay B. Harlow [MVP - Outlook] <Jay_Harlow_***@msn.com> wrote:
> 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"?

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.


Show quoteHide quote
>
> Hope this helps
> Jay
>
> "David" <dfos***@woofix.local.dom> wrote in message
> news:slrnd4b0sq.9am.dfoster@woofix.local.dom...
>> On 2005-03-26, Alejandro Lapeyre <AlejandroLape***@jotmail.com> wrote:
>>> 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.
>>
>>
>
>
Author
27 Mar 2005 8:10 PM
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:

>>> 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.)
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


Show quoteHide quote
"David" <dfos***@woofix.local.dom> wrote in message
news:slrnd4c73t.b53.dfoster@woofix.local.dom...
> On 2005-03-27, Jay B. Harlow [MVP - Outlook] <Jay_Harlow_***@msn.com>
> wrote:
>> 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"?
>
> 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.
>
>
>>
>> Hope this helps
>> Jay
>>
>> "David" <dfos***@woofix.local.dom> wrote in message
>> news:slrnd4b0sq.9am.dfoster@woofix.local.dom...
>>> On 2005-03-26, Alejandro Lapeyre <AlejandroLape***@jotmail.com> wrote:
>>>> 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.
>>>
>>>
>>
>>
Author
27 Mar 2005 9:27 PM
David
On 2005-03-27, Jay B. Harlow [MVP - Outlook] <Jay_Harlow_***@msn.com> wrote:
> 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.

Sure, where MyCollection is a subclass of CollectionBase that holds
Widgets

For each value as String in MyCollection

still compiles.  As I said, shadowing GetEnumerator can help alleviate,
but not eliminate the problem.


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?

Umm, because the default GetEnumerator returns an untyped IEnumerator
interface.  I honestly don't understand what you're not seeing here.
That's not snarky, I honestly don't understand.

> 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).

Nothing I've said has anything to do with performance optimization
(except for a very quick sidebar mention of value type collections a few
posts ago).


> Going back to your original post:
>
>>>> 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.)
> 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

Okay, I have no idea how to respond to this, since the whole impetus
behind strong typing is so that we can catch errors at compile time
rather than runtime. 

Although, when I think about it a little more, I guess this explains
what I didn't understand above.  "Strongly typed" has different
definitions (see wikipedia).  To me, if a language or feature associates
type with the value but not the variable, that's weakly typed.  VBScript
is weakly typed by that definition, although by your definition VBScript
is still strongly typed where COM objects are concerned since they are
typed at runtime.  In your words, you may have runtime errors rather
than compile time errors.

If that's your definition though, then we need another term for this
discussion, because I usually want typing that's stronger than that.  In
my experience, "strongly typed" in the .Net world usually refers to
compile-time type checking.  In fact, didn't you say something just a
few posts ago about ArrayList not being strongly typed, or was that
somebody else?

>, however you run that risk (runtime
> errors) when using generalized interfaces as IList in any class that
> implements IList.

And IList is untyped. Everything's an Object to IList, and so the
compiler can't enforce typing.  And if I inherit from CollectionBase I
must accept this and other untyped interfaces, even if I don't want
them.  And I seldom do want them unless I'm dealing with certain UI
controls. 

I consider IEnumerator more of a problem than IList since the user will
always have to cast things like IList.Item.  So I know the user has to
be explicit when the type system is broken, which is finen.
IEnumerator, though, can break strong typing without a cast because of
the way the language works.

Anyway, you seem to have your hackles up, and I have no idea why.  I'm
not dissing the writers of CollectionBase here.  It's a very useful
class, and given the lack of templates or generics they had little
choice but to allow weakly typed access.  Virtual validators were a
pretty clever answer to this problem, but they aren't strong typing.
Author
28 Mar 2005 3:27 AM
Jay B. Harlow [MVP - Outlook]
David,
OK, I follow what you are saying.

If strongly typing the Enumerator was important to me. I would define my own
CollectionBase class (ala my CollectionBaseEx in this thread) that used
explicit interface implementation to hide the base GetEnumerator, avoiding
Shadows. Then in the derived collection I would add an explicitly typed
GetEnumerator, which returned a strongly typed Enumerator object. Both the
collection & enumerator would be based on base classes that contained
duplicate code to avoid duplicated code as much as possible...

Something like:

Public Class WidgetCollection
    Inherits CollectionBaseEx

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

    Default Public ReadOnly Property Item(ByVal index As Integer) As Widget
        Get
            Return DirectCast(MyBase.InnerList.Item(index), Widget)
        End Get
    End Property

    Public Function GetEnumerator() As WidgetEnumerator
        Return New WidgetEnumerator(Me.InnerList.GetEnumerator())
    End Function

End Class

Public Class WidgetEnumerator
    Inherits EnumeratorBase

    Friend Sub New(ByVal enumerator As IEnumerator)
        MyBase.New(enumerator)
    End Sub

    Public ReadOnly Property Current() As Widget
        Get
            Return DirectCast(enumerator.Current, Widget)
        End Get
    End Property

End Class

Public Class EnumeratorBase
    Implements IEnumerator

    Private ReadOnly m_enumerator As IEnumerator

    Protected Sub New(ByVal enumerator As IEnumerator)
        If enumerator Is Nothing Then
            Throw New ArgumentNullException("enumerator")
        End If
        m_enumerator = enumerator
    End Sub

    Protected ReadOnly Property Enumerator() As IEnumerator
        Get
            Return m_enumerator
        End Get
    End Property

    Private ReadOnly Property IEnumerator_Current() As Object Implements
IEnumerator.Current
        Get
            Return m_enumerator.Current
        End Get
    End Property

    Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
        Return m_enumerator.MoveNext()
    End Function

    Public Sub Reset() Implements IEnumerator.Reset
        m_enumerator.MoveNext()
    End Sub

End Class

<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 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_GetEnumerator() As IEnumerator Implements
IList.GetEnumerator
        Return m_list.GetEnumerator
    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

The above sample causes a compile error in VS.NET 2003 with your sample!

> For each value as String in MyCollection

VS.NET 2005 (aka Whidbey, due out later in 2005) should simplify defining
Strongly typed collections & enumerators via the new Generics support.

Hope this helps
Jay

Show quoteHide quote
"David" <dfos***@woofix.local.dom> wrote in message
news:slrnd4djn9.cvg.dfoster@woofix.local.dom...
> On 2005-03-27, Jay B. Harlow [MVP - Outlook] <Jay_Harlow_***@msn.com>
> wrote:
>> 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.
>
> Sure, where MyCollection is a subclass of CollectionBase that holds
> Widgets
>
> For each value as String in MyCollection
>
> still compiles.  As I said, shadowing GetEnumerator can help alleviate,
> but not eliminate the problem.
>
>
> 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?
>
> Umm, because the default GetEnumerator returns an untyped IEnumerator
> interface.  I honestly don't understand what you're not seeing here.
> That's not snarky, I honestly don't understand.
>
>> 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).
>
> Nothing I've said has anything to do with performance optimization
> (except for a very quick sidebar mention of value type collections a few
> posts ago).
>
>
>> Going back to your original post:
>>
>>>>> 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.)
>> 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
>
> Okay, I have no idea how to respond to this, since the whole impetus
> behind strong typing is so that we can catch errors at compile time
> rather than runtime.
>
> Although, when I think about it a little more, I guess this explains
> what I didn't understand above.  "Strongly typed" has different
> definitions (see wikipedia).  To me, if a language or feature associates
> type with the value but not the variable, that's weakly typed.  VBScript
> is weakly typed by that definition, although by your definition VBScript
> is still strongly typed where COM objects are concerned since they are
> typed at runtime.  In your words, you may have runtime errors rather
> than compile time errors.
>
> If that's your definition though, then we need another term for this
> discussion, because I usually want typing that's stronger than that.  In
> my experience, "strongly typed" in the .Net world usually refers to
> compile-time type checking.  In fact, didn't you say something just a
> few posts ago about ArrayList not being strongly typed, or was that
> somebody else?
>
>>, however you run that risk (runtime
>> errors) when using generalized interfaces as IList in any class that
>> implements IList.
>
> And IList is untyped. Everything's an Object to IList, and so the
> compiler can't enforce typing.  And if I inherit from CollectionBase I
> must accept this and other untyped interfaces, even if I don't want
> them.  And I seldom do want them unless I'm dealing with certain UI
> controls.
>
> I consider IEnumerator more of a problem than IList since the user will
> always have to cast things like IList.Item.  So I know the user has to
> be explicit when the type system is broken, which is finen.
> IEnumerator, though, can break strong typing without a cast because of
> the way the language works.
>
> Anyway, you seem to have your hackles up, and I have no idea why.  I'm
> not dissing the writers of CollectionBase here.  It's a very useful
> class, and given the lack of templates or generics they had little
> choice but to allow weakly typed access.  Virtual validators were a
> pretty clever answer to this problem, but they aren't strong typing.
>
>
Author
28 Mar 2005 3:34 AM
Jay B. Harlow [MVP - Outlook]
Doh!
> Both the collection & enumerator would be based on base classes that
> contained duplicate code to avoid duplicated code as much as possible...
That's poorly worded. Should read:

Both the collection & enumerator would be based on base classes that
contained common code to all collections & enumerators to avoid duplicated
code as much as possible...

And I agree the "real" problem is the way IEnumerator & IList are defined as
they are defined very generalized to ensure maximum polymorphism...

Hope this helps
Jay

Show quoteHide quote
"Jay B. Harlow [MVP - Outlook]" <Jay_Harlow_***@msn.com> wrote in message
news:%23PF1aY0MFHA.1476@TK2MSFTNGP09.phx.gbl...
> David,
> OK, I follow what you are saying.
>
> If strongly typing the Enumerator was important to me. I would define my
> own CollectionBase class (ala my CollectionBaseEx in this thread) that
> used explicit interface implementation to hide the base GetEnumerator,
> avoiding Shadows. Then in the derived collection I would add an explicitly
> typed GetEnumerator, which returned a strongly typed Enumerator object.
> Both the collection & enumerator would be based on base classes that
> contained duplicate code to avoid duplicated code as much as possible...
>
> Something like:
>
> Public Class WidgetCollection
>    Inherits CollectionBaseEx
>
>    Public Sub Add(ByVal value As Widget)
>        MyBase.InnerList.Add(value)
>    End Sub
>
>    Default Public ReadOnly Property Item(ByVal index As Integer) As Widget
>        Get
>            Return DirectCast(MyBase.InnerList.Item(index), Widget)
>        End Get
>    End Property
>
>    Public Function GetEnumerator() As WidgetEnumerator
>        Return New WidgetEnumerator(Me.InnerList.GetEnumerator())
>    End Function
>
> End Class
>
> Public Class WidgetEnumerator
>    Inherits EnumeratorBase
>
>    Friend Sub New(ByVal enumerator As IEnumerator)
>        MyBase.New(enumerator)
>    End Sub
>
>    Public ReadOnly Property Current() As Widget
>        Get
>            Return DirectCast(enumerator.Current, Widget)
>        End Get
>    End Property
>
> End Class
>
> Public Class EnumeratorBase
>    Implements IEnumerator
>
>    Private ReadOnly m_enumerator As IEnumerator
>
>    Protected Sub New(ByVal enumerator As IEnumerator)
>        If enumerator Is Nothing Then
>            Throw New ArgumentNullException("enumerator")
>        End If
>        m_enumerator = enumerator
>    End Sub
>
>    Protected ReadOnly Property Enumerator() As IEnumerator
>        Get
>            Return m_enumerator
>        End Get
>    End Property
>
>    Private ReadOnly Property IEnumerator_Current() As Object Implements
> IEnumerator.Current
>        Get
>            Return m_enumerator.Current
>        End Get
>    End Property
>
>    Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
>        Return m_enumerator.MoveNext()
>    End Function
>
>    Public Sub Reset() Implements IEnumerator.Reset
>        m_enumerator.MoveNext()
>    End Sub
>
> End Class
>
> <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 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_GetEnumerator() As IEnumerator Implements
> IList.GetEnumerator
>        Return m_list.GetEnumerator
>    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
>
> The above sample causes a compile error in VS.NET 2003 with your sample!
>
>> For each value as String in MyCollection
>
> VS.NET 2005 (aka Whidbey, due out later in 2005) should simplify defining
> Strongly typed collections & enumerators via the new Generics support.
>
> Hope this helps
> Jay
>
> "David" <dfos***@woofix.local.dom> wrote in message
> news:slrnd4djn9.cvg.dfoster@woofix.local.dom...
>> On 2005-03-27, Jay B. Harlow [MVP - Outlook] <Jay_Harlow_***@msn.com>
>> wrote:
>>> 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.
>>
>> Sure, where MyCollection is a subclass of CollectionBase that holds
>> Widgets
>>
>> For each value as String in MyCollection
>>
>> still compiles.  As I said, shadowing GetEnumerator can help alleviate,
>> but not eliminate the problem.
>>
>>
>> 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?
>>
>> Umm, because the default GetEnumerator returns an untyped IEnumerator
>> interface.  I honestly don't understand what you're not seeing here.
>> That's not snarky, I honestly don't understand.
>>
>>> 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).
>>
>> Nothing I've said has anything to do with performance optimization
>> (except for a very quick sidebar mention of value type collections a few
>> posts ago).
>>
>>
>>> Going back to your original post:
>>>
>>>>>> 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.)
>>> 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
>>
>> Okay, I have no idea how to respond to this, since the whole impetus
>> behind strong typing is so that we can catch errors at compile time
>> rather than runtime.
>>
>> Although, when I think about it a little more, I guess this explains
>> what I didn't understand above.  "Strongly typed" has different
>> definitions (see wikipedia).  To me, if a language or feature associates
>> type with the value but not the variable, that's weakly typed.  VBScript
>> is weakly typed by that definition, although by your definition VBScript
>> is still strongly typed where COM objects are concerned since they are
>> typed at runtime.  In your words, you may have runtime errors rather
>> than compile time errors.
>>
>> If that's your definition though, then we need another term for this
>> discussion, because I usually want typing that's stronger than that.  In
>> my experience, "strongly typed" in the .Net world usually refers to
>> compile-time type checking.  In fact, didn't you say something just a
>> few posts ago about ArrayList not being strongly typed, or was that
>> somebody else?
>>
>>>, however you run that risk (runtime
>>> errors) when using generalized interfaces as IList in any class that
>>> implements IList.
>>
>> And IList is untyped. Everything's an Object to IList, and so the
>> compiler can't enforce typing.  And if I inherit from CollectionBase I
>> must accept this and other untyped interfaces, even if I don't want
>> them.  And I seldom do want them unless I'm dealing with certain UI
>> controls.
>>
>> I consider IEnumerator more of a problem than IList since the user will
>> always have to cast things like IList.Item.  So I know the user has to
>> be explicit when the type system is broken, which is finen.
>> IEnumerator, though, can break strong typing without a cast because of
>> the way the language works.
>>
>> Anyway, you seem to have your hackles up, and I have no idea why.  I'm
>> not dissing the writers of CollectionBase here.  It's a very useful
>> class, and given the lack of templates or generics they had little
>> choice but to allow weakly typed access.  Virtual validators were a
>> pretty clever answer to this problem, but they aren't strong typing.
>>
>>
>
>
Author
28 Mar 2005 11:48 PM
David
On 2005-03-28, Jay B. Harlow [MVP - Outlook] <Jay_Harlow_***@msn.com> wrote:
> David,
> OK, I follow what you are saying.
>
> If strongly typing the Enumerator was important to me. I would define my own
> CollectionBase class (ala my CollectionBaseEx in this thread) that used
> explicit interface implementation to hide the base GetEnumerator, avoiding
> Shadows. Then in the derived collection I would add an explicitly typed
> GetEnumerator, which returned a strongly typed Enumerator object.

Like I said, at one point I thought this would really bother me but in
practice it turns out, not so much.  Although, and this surprised me, it
seems I do have a shadowed GetEnumerator in my typed collection classes.
I must have added it last fall when I moved my generator out of
CodeSmith.

I might be missing something, but I don't see what the classes below buy
me beyond what CollectionBase offers.  What invalid code fails on your
classes but still compiles on a CollectionBase subclass with a shadowed
GetEnumerator()?




Both the
Show quoteHide quote
> collection & enumerator would be based on base classes that contained
> duplicate code to avoid duplicated code as much as possible...
>
> Something like:
>
> Public Class WidgetCollection
>     Inherits CollectionBaseEx
>
>     Public Sub Add(ByVal value As Widget)
>         MyBase.InnerList.Add(value)
>     End Sub
>
>     Default Public ReadOnly Property Item(ByVal index As Integer) As Widget
>         Get
>             Return DirectCast(MyBase.InnerList.Item(index), Widget)
>         End Get
>     End Property
>
>     Public Function GetEnumerator() As WidgetEnumerator
>         Return New WidgetEnumerator(Me.InnerList.GetEnumerator())
>     End Function
>
> End Class
>
> Public Class WidgetEnumerator
>     Inherits EnumeratorBase
>
>     Friend Sub New(ByVal enumerator As IEnumerator)
>         MyBase.New(enumerator)
>     End Sub
>
>     Public ReadOnly Property Current() As Widget
>         Get
>             Return DirectCast(enumerator.Current, Widget)
>         End Get
>     End Property
>
> End Class
>
> Public Class EnumeratorBase
>     Implements IEnumerator
>
>     Private ReadOnly m_enumerator As IEnumerator
>
>     Protected Sub New(ByVal enumerator As IEnumerator)
>         If enumerator Is Nothing Then
>             Throw New ArgumentNullException("enumerator")
>         End If
>         m_enumerator = enumerator
>     End Sub
>
>     Protected ReadOnly Property Enumerator() As IEnumerator
>         Get
>             Return m_enumerator
>         End Get
>     End Property
>
>     Private ReadOnly Property IEnumerator_Current() As Object Implements
> IEnumerator.Current
>         Get
>             Return m_enumerator.Current
>         End Get
>     End Property
>
>     Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
>         Return m_enumerator.MoveNext()
>     End Function
>
>     Public Sub Reset() Implements IEnumerator.Reset
>         m_enumerator.MoveNext()
>     End Sub
>
> End Class
>
><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 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_GetEnumerator() As IEnumerator Implements
> IList.GetEnumerator
>         Return m_list.GetEnumerator
>     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
>
> The above sample causes a compile error in VS.NET 2003 with your sample!
>
>> For each value as String in MyCollection
>
> VS.NET 2005 (aka Whidbey, due out later in 2005) should simplify defining
> Strongly typed collections & enumerators via the new Generics support.
>
Author
29 Mar 2005 2:53 AM
Jay B. Harlow [MVP - Outlook]
David,
> I might be missing something, but I don't see what the classes below buy
> me beyond what CollectionBase offers.  What invalid code fails on your
> classes but still compiles on a CollectionBase subclass with a shadowed
> GetEnumerator()?
Three things that I know of:
- It avoid the Shadows, as I stated elsewhere in this thread Shadows is
really intended for Versioning
- More importantly it prevents you from casting the class into a
CollectionBase variable & using the base CollectionBase.GetEnumerator. The
IList.GetEnumerator is available as expected.
- Most importantly it allows you to use any IList implementation instead of
just ArrayList

See my other post in this thread where I explain CollectionBaseEx &
DictionaryBaseEx.

Hope this helps
Jay


Show quoteHide quote
"David" <dfos***@woofix.local.dom> wrote in message
news:slrnd4ggao.57l.dfoster@woofix.local.dom...
> On 2005-03-28, Jay B. Harlow [MVP - Outlook] <Jay_Harlow_***@msn.com>
> wrote:
>> David,
>> OK, I follow what you are saying.
>>
>> If strongly typing the Enumerator was important to me. I would define my
>> own
>> CollectionBase class (ala my CollectionBaseEx in this thread) that used
>> explicit interface implementation to hide the base GetEnumerator,
>> avoiding
>> Shadows. Then in the derived collection I would add an explicitly typed
>> GetEnumerator, which returned a strongly typed Enumerator object.
>
> Like I said, at one point I thought this would really bother me but in
> practice it turns out, not so much.  Although, and this surprised me, it
> seems I do have a shadowed GetEnumerator in my typed collection classes.
> I must have added it last fall when I moved my generator out of
> CodeSmith.
>
> I might be missing something, but I don't see what the classes below buy
> me beyond what CollectionBase offers.  What invalid code fails on your
> classes but still compiles on a CollectionBase subclass with a shadowed
> GetEnumerator()?
>
Author
27 Mar 2005 5:08 AM
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/default.asp?url=/library/en-us/dndotnet/html/highperfmanagedapps.asp

Hope this helps
Jay




Show quoteHide quote
"Alejandro Lapeyre" <AlejandroLape***@jotmail.com> wrote in message
news:OSzFpniMFHA.244@tk2msftngp13.phx.gbl...
> Why bother inheriting from CollectionBase?
>
> Just implement the interfaces (IList and others as needed) and your save
> yourself one wrapper.
>
> Best Regards,
> Alejandro Lapeyre
>
>
> "Jay B. Harlow [MVP - Outlook]" <Jay_Harlow_***@msn.com> escribió en el
> mensaje news:OPTMYLiMFHA.3420@tk2msftngp13.phx.gbl...
>> 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
>>
>> "Dennis" <Den***@discussions.microsoft.com> wrote in message
>> news:B5527DF7-A000-4772-8352-6269131CB7DE@microsoft.com...
>>>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?
>>>
>>> "Cor Ligthert" wrote:
>>>
>>>> Dennis,
>>>>
>>>> Why you inherit from Arraylist and not direct from the collectionbase
>>>>
>>>> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemcollectionscollectionbaseclasstopic.asp
>>>>
>>>> A nice sample is included in that page
>>>>
>>>> In my opinion is that simpler and more consistent.
>>>>
>>>> I hope this helps?
>>>>
>>>> Cor
>>>>
>>>>
>>>>
>>
>>
>
>
Author
26 Mar 2005 5:37 PM
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

Show quoteHide quote
"Jay B. Harlow [MVP - Outlook]" <Jay_Harlow_***@msn.com> escribió en el
mensaje news:OPTMYLiMFHA.3420@tk2msftngp13.phx.gbl...
> 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
>
> "Dennis" <Den***@discussions.microsoft.com> wrote in message
> news:B5527DF7-A000-4772-8352-6269131CB7DE@microsoft.com...
>>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?
>>
>> "Cor Ligthert" wrote:
>>
>>> Dennis,
>>>
>>> Why you inherit from Arraylist and not direct from the collectionbase
>>>
>>> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemcollectionscollectionbaseclasstopic.asp
>>>
>>> A nice sample is included in that page
>>>
>>> In my opinion is that simpler and more consistent.
>>>
>>> I hope this helps?
>>>
>>> Cor
>>>
>>>
>>>
>
>
Author
25 Mar 2005 12:18 PM
Herfried K. Wagner [MVP]
"Dennis" <Den***@discussions.microsoft.com> schrieb:
>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>

--
M S   Herfried K. Wagner
M V P  <URL:http://dotnet.mvps.org/>
V B   <URL:http://classicvb.org/petition/>
Author
25 Mar 2005 8:02 PM
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

Show quoteHide quote
"Dennis" <Den***@discussions.microsoft.com> wrote in message
news:22967A9D-A366-4B18-8B28-0EACFD1A7C57@microsoft.com...
>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
> --
> Dennis in Houston
Author
25 Mar 2005 8:29 PM
J L
Hi Jay,
Can you create a strongly typed SortedList also? If so how?

TIA,
John

On Fri, 25 Mar 2005 14:02:15 -0600, "Jay B. Harlow [MVP - Outlook]"
<Jay_Harlow_***@msn.com> wrote:

Show quoteHide quote
>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
>
>"Dennis" <Den***@discussions.microsoft.com> wrote in message
>news:22967A9D-A366-4B18-8B28-0EACFD1A7C57@microsoft.com...
>>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
>> --
>> Dennis in Houston
>
Author
25 Mar 2005 9:15 PM
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---


Show quoteHide quote
"J L" <j***@marymonte.com> wrote in message
news:f4t841hj6vl9iqd10gs0i7riuf0fkv3ntk@4ax.com...
> Hi Jay,
> Can you create a strongly typed SortedList also? If so how?
>
> TIA,
> John
>
> On Fri, 25 Mar 2005 14:02:15 -0600, "Jay B. Harlow [MVP - Outlook]"
> <Jay_Harlow_***@msn.com> wrote:
>
>>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
>>
>>"Dennis" <Den***@discussions.microsoft.com> wrote in message
>>news:22967A9D-A366-4B18-8B28-0EACFD1A7C57@microsoft.com...
>>>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
>>> --
>>> Dennis in Houston
>>
>
Author
25 Mar 2005 10:03 PM
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

On Fri, 25 Mar 2005 15:15:34 -0600, "Jay B. Harlow [MVP - Outlook]"
<Jay_Harlow_***@msn.com> wrote:

Show quoteHide quote
>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---
>
>
>"J L" <j***@marymonte.com> wrote in message
>news:f4t841hj6vl9iqd10gs0i7riuf0fkv3ntk@4ax.com...
>> Hi Jay,
>> Can you create a strongly typed SortedList also? If so how?
>>
>> TIA,
>> John
>>
>> On Fri, 25 Mar 2005 14:02:15 -0600, "Jay B. Harlow [MVP - Outlook]"
>> <Jay_Harlow_***@msn.com> wrote:
>>
>>>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
>>>
>>>"Dennis" <Den***@discussions.microsoft.com> wrote in message
>>>news:22967A9D-A366-4B18-8B28-0EACFD1A7C57@microsoft.com...
>>>>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
>>>> --
>>>> Dennis in Houston
>>>
>>
>
Author
25 Mar 2005 9:37 PM
Dennis
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?

Show quoteHide quote
"Jay B. Harlow [MVP - Outlook]" wrote:

> 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
>
> "Dennis" <Den***@discussions.microsoft.com> wrote in message
> news:22967A9D-A366-4B18-8B28-0EACFD1A7C57@microsoft.com...
> >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
> > --
> > Dennis in Houston
>
>
>