Terry,
| Is the .Net equivalent of the VB6 collection object a
| System.Collections.Hashtable?
Microsoft.VisualBasic.Collection is .NET's equivalent to VB6's collection.
However I would not recommend using it as it normally does more then you
really want, plus it is 1 based as opposed to 0 based. 0 based collections
are prevalent in the Framework.
ArrayList & HashTable are .NET 1.x "common" collection's while List(Of T) &
Dictionary(Of T) are .NET 2.0 "common" collection.
By "common" I mean most versatile, where you would have used Collection in
VB6.
ArrayList & List(Of T) are used when you have an ordered collection of items
that do not have a key.
HashTable & Dictionary(Of T) are used when you have an unordered collection
of items that have a key.
CollectionBase, ReadOnlyCollectionBase and DictionaryBase are the .NET 1.x
way of doing things.
Collection(Of T), ReadonlyCollection(Of T), and KeyedCollection(Of T) are
the .NET 2.0 way of doing things.
NOTE: KeyedCollection(Of T) can be used for an ordered collection w/keys;
while DictionaryBase cannot.
| Is the .Net equivelant (for the generic case):
| Public Function GetEnumerator() as
| System.Collections.Generic.Dictionary.Enumerator
| return mPersons.GetEnumerator()
| end function
Yes call GetEnumerator is the equivelant, as I believe you found out. Be
careful some collections such as Dictionary(OF T) & HashTable are actually
collections of key/value pairs. Which means that the enumerator returns a
structure that contains both the key & the value. KeyedCollection(Of T)
returns an enumerator of just the value, as it is an IList(Of T) first, that
maintains a second collection of the keys...
--
Hope this helps
Jay B. Harlow [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley -
http://www.tsbradley.net
| Hi Jay,
| Thanks for the help!
|
| First, I had just spent several hours on a responce to you (along with
other
| things)and when I 'posted' it, I was taken back to the logon page and my
| entire response was lost! Is that normal? Is there a timeout on this
site
| or was it just a glitch?
|
| Ok, so I can use interfaces in the same way as I did in VB6. Guess I got
| off on the wrong foot when the IDE inserted public readonly properties
using
| the same name as soon as I typed in the Implements clasue. Thought I had
to
| leave the property names alone (as in VB6).
| As far as the custom collections go, I really would prefer NOT to expose
| 'Add', 'Remove', etc to the client objects. This is a commercial product
| and the API it exposes needs to be 'clean', and not contain methods and
| properties that they should not use.
| If I inherit from one of the base collection classes, then I will expose
all
| these methods. So, I wish to wrap one of the collection classes as I did
in
| VB6. Is the .Net equivalent of the VB6 collection object a
| System.Collections.Hashtable? And if I wanted to use a generic collection
| would I use a 'Dictionary' as the closest thing to the VB6 collection
type?
|
| In VB6 you provided 'enumeration' for your custom collections by including
| the following code in your class:
| Public Function NewEnum() As IUnknown
| Set NewEnum = mPersons.[_NewEnum]
| End Function
| and setting the ProcedureId to -4 (Under Procedure Attributes/Advanced)
| Is the .Net equivelant (for the generic case):
| Public Function GetEnumerator() as
| System.Collections.Generic.Dictionary.Enumerator
| return mPersons.GetEnumerator()
| end function
|
| Thanks again for all your help!!!
| --
| Terry
|
|
| "Jay B. Harlow [MVP - Outlook]" wrote:
|
| > Terry,
| > In addition to the other comments:
| >
| > | So, is this the best (only) way to accomplish what I was doing using
| > | interfaces in VB6?
| >
| > Rather then use Shadows & inheritance.
| >
| > I would recommend to use "explicit interface implementation" something
like:
| >
| > Public Interface IReadonlyPerson
| >
| > ReadOnly Property FirstName() As String
| > ReadOnly Property LastName() As String
| >
| > End Interface
| >
| > Public Class Person
| > Implements IReadonlyPerson
| >
| > Public Property FirstName() As String
| > Get
| >
| > End Get
| > Set(ByVal value As String)
| >
| > End Set
| > End Property
| >
| > Public Property LastName() As String
| > Get
| >
| > End Get
| > Set(ByVal value As String)
| >
| > End Set
| > End Property
| >
| > #Region " IReadonlyPerson support "
| >
| > Private ReadOnly Property IReadonlyPerson_FirstName() As String
| > Implements IReadonlyPerson.FirstName
| > Get
| > Return FirstName
| > End Get
| > End Property
| >
| > Private ReadOnly Property IReadonlyPerson_LastName() As String
| > Implements IReadonlyPerson.LastName
| > Get
| > Return LastName
| > End Get
| > End Property
| >
| > #End Region
| >
| > End Class
| >
| > Unfortunately any code that receives an IReadonlyPerson value can simply
| > cast it back to Person to gain full access to the object. If you want a
true
| > Readonly Person I would create a Readonly Person class that delegated
| > (wrapped) a Person object. Something like:
| >
| > Public Class ReadonlyPerson
| >
| > Private ReadOnly m_person As Person
| >
| > Public Sub New(ByVal person As Person)
| > m_person = person
| > End Sub
| >
| > Public ReadOnly Property FirstName() As String
| > Get
| > Return m_person.FirstName
| > End Get
| > End Property
| > Public ReadOnly Property LastName() As String
| > Get
| > Return m_person.LastName
| > End Get
| > End Property
| >
| > End Class
| >
| > Public Class Person
| >
| > Public Property FirstName() As String
| > Get
| >
| > End Get
| > Set(ByVal value As String)
| >
| > End Set
| > End Property
| >
| > Public Property LastName() As String
| > Get
| >
| > End Get
| > Set(ByVal value As String)
| >
| > End Set
| > End Property
| >
| > Public Function AsReadonly() As ReadonlyPerson
| > Return New ReadonlyPerson(Me)
| > End Function
| >
| > End Class
| >
| > Of course using Reflection one could break the contract with
ReadonlyPerson,
| > however that would be more effort...
| >
| > | And, how do I implement 'enumeration' for my custom
| > | collections in .Net? That is with out giving them remove, clear and
any
| > | other 'write' type functions that are implemented in the base class.
| > In .NET 1.x I would recommend inheriting from
| > System.Collections.CollectionBase:
| >
| > Public Class PersonCollection
| > Inherits System.Collections.CollectionBase
| >
| > Default Public Property Item(ByVal index As Integer) As Person
| > Get
| > Return DirectCast(List.Item(index), Person)
| > End Get
| > Set(ByVal value As Person)
| > List.Item(index) = value
| > End Set
| > End Property
| >
| > Public Sub Add(ByVal value As Person)
| > List.Add(value)
| > End Sub
| >
| > Public Function Contains(ByVal value As Person) As Boolean
| > Return List.Contains(value)
| > End Function
| >
| > Public Function IndexOf(ByVal value As Person) As Integer
| > Return List.IndexOf(value)
| > End Function
| >
| > Public Sub Insert(ByVal index As Integer, ByVal value As Person)
| > List.Insert(index, value)
| > End Sub
| >
| > Public Sub Remove(ByVal value As Person)
| > List.Remove(value)
| > End Sub
| >
| > Protected Overrides Sub OnValidate(ByVal value As Object)
| > If TypeOf value Is Person Then Return
| > Throw New InvalidCastException
| > End Sub
| >
| > End Class
| >
| > The OnValidate ensures that only Person objects are added to the
collection
| > when using the IList interface exposed by the collection...
| > CollectionBase.List (as above) uses the IList interface, while
| > CollectionBase.InnerList uses the contained (wrapped) ArrayList object.
| > Primarily InnerList.Add will not cause the OnValidate event to be
raised...
| >
| > In .NET 2.0 I would recommend inheriting from Collection(Of T).
| >
| > Public Class PersonCollection
| > Inherits System.Collections.ObjectModel.Collection(Of Person)
| >
| > End Class
| >
| > YES! that is all the code you need with .NET 2.0!
| >
| >
| > --
| > Hope this helps
| > Jay B. Harlow [MVP - Outlook]
| > ..NET Application Architect, Enthusiast, & Evangelist
| > T.S. Bradley -
http://www.tsbradley.net
| >
| >
| > | > |I am converting (attempting) some vb6 code that makes vast use of
| > interfaces.
| > | One of the major uses is to be able to split out Read-only access to
an
| > | obect. Let me give you a simple (contrived) example:
| > | In Project RoObjDefs:
| > | RoPerson.cls file:
| > | Public Property Get FirstName() as String
| > | Public Property Get LastName() as String
| > | <end of file RoPerson.cls>
| > | RoPersons.cls file
| > | Public Function Count() as Integer
| > | Public Function Item(Index as Variant) as Person
| > | Public Function NewEnum() as IUnknown
| > | <end of file RoPersons.cls>
| > |
| > | Then in Project RwObjDefs:
| > | Person.cls file
| > | Implements RoObjDefs.RoPerson
| > | Private mFirstName as String
| > | Private mFirstName as String
| > | ...
| > | Public Property Get FirstName() as String
| > | FirstName = mFirstName
| > | End Property
| > | Public Property Set FirstName(byval val as string)
| > | mFirstName = val
| > | End Properety
| > | ...
| > | Private Property Get RoPerson_FirstName() as String
| > | RoPerson_FirstName = mFirstName
| > | End Property
| > | ...
| > | <end of Person.cls file>
| > |
| > | In file Persons.cls
| > | mPersons as collection
| > | ...(Code for add, item, remove, clear...)
| > | Public Function NewEnum() As IUnknown
| > | Set NewEnum = mPersons.[_NewEnum]
| > | End Function
| > | ...(implement the RO functions, like in Person class above)
| > | <end of Persons.cls>
| > |
| > | I could then 'cast' a Person to an RoPerson, when I only wanted to
give
| > out
| > | a readonly interface.
| > | I find when I attempt this that I can not do it though the use of
| > | interfaces. At least I cant if I want the properties to have the same
| > name
| > | on both of the interfaces.
| > | My guess is that I should now do this with inheritance. For example:
| > |
| > | Public Class RoPerson
| > | Protected mFirstName as string
| > | Public Readonly Property FirstName() as string
| > | Return mFirstName
| > | End Property
| > | ...
| > | and then in another class:
| > | Public Class Person
| > | Inherits RoPerson
| > | Public Shadows Property FirstName() As String
| > | Get
| > | Return MyBase.FirstName
| > | End Get
| > | Set(byval value as string)
| > | MyBase.mFirstName = value
| > | End Set
| > | ...
| > |
| > | Then like under VB6, I could 'cast' the object to its base when
returning
| > a
| > | reference to a readonly user.
| > | So, is this the best (only) way to accomplish what I was doing using
| > | interfaces in VB6? And, how do I implement 'enumeration' for my
custom
| > | collections in .Net? That is with out giving them remove, clear and
any
| > | other 'write' type functions that are implemented in the base class.
| > |
| > | Thanks in advance for your guidance.
| > | --
| > | Terry
| >
| >
| >