|
web
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
ArrayList Strongly TypedHowever, 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 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 On 2005-03-25, J L <j***@marymonte.com> wrote:
> Hi Dennis, It would work, but...> I am a .Net newbie so let me ask...why go to the trouble of creating > the FrameList class? Wouldn't this work > Yes, you are. The line> myFrameStructure = ctype(myList(0), FrameStructure) > with myFrameStructure > messagebox.show(.first & vbcrlf & .second) > end with > > Am I missing something about strong typing or what? > myFrameStructure = ctype(myList(0), FrameStructure) isn't strongly typed. If you accidently add something other than aFrameStructure 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. 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 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 > > > Dennis,
>I guess the primary reason that I inheirt from the arraylist is the sort In my opinion you get a nicer class (with more control from your own and not > 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 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 Dennis,
> What is the As I stated CollectionBase allows you to define Strongly Typed collections!> advantage of using the collectionbase over the arraylist? 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 Public Shadows Sub Add(value As FrameStructure)> Inherits ArrayList MyBase.Add(value) End Sub > Default Public Shadows Property Item(ByVal Index As Integer) As I can define an ArrayList variable that holds a FrameList> FrameStructure 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 CollectionBase exposes the contained ArrayList as InnerList your custom > property in my strongly typed arraylist class using Icomparer. 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 >> >> >> 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 >>> >>> >>> > > On 2005-03-26, Alejandro Lapeyre <AlejandroLape***@jotmail.com> wrote:
> Why bother inheriting from CollectionBase? I'm of two minds here...> > Just implement the interfaces (IList and others as needed) and your save > yourself one wrapper. 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. David,
> On the other hand, CollectionBase is a huge hole in the type system What do you mean by "typed enumerations"? I have not any problems with > since you can't get typed enumerations out of it 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. > > On 2005-03-27, Jay B. Harlow [MVP - Outlook] <Jay_Harlow_***@msn.com> wrote:
> David, Strong typing in a For Each enumeration.>> 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 A virtual (overridable) GetEnumerator of some type, I suppose.> implementation if CollectionBase.GetEnumerator! > > Were you attempting to replace (Shadow) CollectionBase.GetEnumerator? > > What specifically are you expecting in a "typed enumerations"? "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. >> >> > > 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. How do you see an overridable GetEnumerator providing strong typing? Based > "Expecting" is definitely the wrong term there, BTW, I understand why > this can't be. 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 I am trying to figure out what & how this "huge hole in the type system" you >>> 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.) 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. >>> >>> >> >> On 2005-03-27, Jay B. Harlow [MVP - Outlook] <Jay_Harlow_***@msn.com> wrote:
> David, Sure, where MyCollection is a subclass of CollectionBase that holds>> 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. 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... Umm, because the default GetEnumerator returns an untyped IEnumerator> > >> 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? interface. I honestly don't understand what you're not seeing here. That's not snarky, I honestly don't understand. > Based Nothing I've said has anything to do with performance optimization> 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). (except for a very quick sidebar mention of value type collections a few posts ago). > Going back to your original post: Okay, I have no idea how to respond to this, since the whole impetus> >>>> 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 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 And IList is untyped. Everything's an Object to IList, and so the> errors) when using generalized interfaces as IList in any class that > implements IList. 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. 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. > > Doh!
> Both the collection & enumerator would be based on base classes that That's poorly worded. Should read:> contained duplicate code to avoid duplicated code as much as possible... 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. >> >> > > On 2005-03-28, Jay B. Harlow [MVP - Outlook] <Jay_Harlow_***@msn.com> wrote:
> David, Like I said, at one point I thought this would really bother me but in> 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. 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. > David,
> I might be missing something, but I don't see what the classes below buy Three things that I know of:> me beyond what CollectionBase offers. What invalid code fails on your > classes but still compiles on a CollectionBase subclass with a shadowed > GetEnumerator()? - 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()? > 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 The primary reason I would consider avoiding the wrapper would be if > yourself one wrapper. 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 >>>> >>>> >>>> >> >> > > 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 >>> >>> >>> > > "Dennis" <Den***@discussions.microsoft.com> schrieb: You may want to translate the code produced by the collection generator >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. 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/> 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 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 > 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 >> > 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 >>> >> > 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 > > > |
|||||||||||||||||||||||