|
Dit artikel is gepubliceerd op zondag 31 juli 2011 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.
Veronderstel volgende item types : Visual Basic 2010 Broncode Option Strict OnImports System.Collections Public Class FingerEnd ClassPublic Class Thumb : Inherits FingerEnd ClassPublic Class IndexFinger : Inherits FingerEnd ClassPublic Class MiddleFinger : Inherits FingerEnd ClassPublic Class RingFinger : Inherits FingerEnd ClassPublic Class LittleFinger : Inherits FingerEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Een type als onderstaande Hand kan je zien als een verzameling of collectie van Fingers : Visual Basic 2010 Broncode Namespace SimpleHand Public Class Hand Public ReadOnly Thumb As New Thumb Public ReadOnly IndexFinger As New IndexFinger Public ReadOnly MiddleFinger As New MiddleFinger Public ReadOnly RingFinger As New RingFinger Public ReadOnly LittleFinger As New LittleFinger End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Met bovenstaand collectietype kunnen we weinig aan. Het is bijvoorbeeld niet mogelijk over de elementen van deze collectie te itereren. 22.2.1. De System.Collections.IEnumerable InterfaceOm dit toch te kunnen moeten we de IEnumerable interface implementeren.
Deze is als volgt gedefinieerd : Public Interface IEnumerable Function GetEnumerator() As IEnumerator End Interface De IEnumerator interface ziet er zo uit : Public Interface IEnumerator Function MoveNext() As Boolean ReadOnly Property Current() As Object Sub Reset() End Interface In onderstaand voorbeeld zien we hoe we de IEnumerable interface in ons type Hand kunnen implementeren : Visual Basic 2010 Broncode Namespace IEnumerableHand Public Class Hand : Implements IEnumerable Public ReadOnly Thumb As New Thumb Public ReadOnly IndexFinger As New IndexFinger Public ReadOnly MiddleFinger As New MiddleFinger Public ReadOnly RingFinger As New RingFinger Public ReadOnly LittleFinger As New LittleFinger Public Function GetEnumerator() As IEnumerator _ Implements IEnumerable. GetEnumerator GetEnumerator = New HandEnumerator( Me) End Function End Class Public Class HandEnumerator : Implements IEnumerator Public Sub New( ByVal items As Hand) _Items = items End Sub Private _Items As Hand Private _Cursor As Finger Public ReadOnly Property Current() As Object _ Implements IEnumerator. Current Get Current = _Cursor End Get End Property Public Function MoveNext() As Boolean Implements IEnumerator. MoveNext MoveNext = True If _Cursor Is Nothing Then _Cursor = _Items.Thumb ElseIf _Cursor Is _Items.Thumb Then _Cursor = _Items.IndexFinger ElseIf _Cursor Is _Items.IndexFinger Then _Cursor = _Items.MiddleFinger ElseIf _Cursor Is _Items.MiddleFinger Then _Cursor = _Items.RingFinger ElseIf _Cursor Is _Items.RingFinger Then _Cursor = _Items.LittleFinger Else _Cursor = Nothing End If If _Cursor Is Nothing Then MoveNext = False End Function Public Sub Reset() Implements IEnumerator. Reset _Cursor = Nothing End Sub End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Meer details over de interfaces IEnumerable en IEnumerator vind je in de desbetreffende topics.
Eens de IEnumerable interface is geïmplementeerd in ons type Hand kan men een object van dit type in enumereerbare context gebruiken.
Bijvoorbeeld in een For Each iteratie : Visual Basic 2010 Broncode Namespace IEnumerableHand Class Client Public Shared Sub Main() Dim hand1 As IEnumerable = New Hand For Each element As Object In hand1 Console.WriteLine(element) Next Console.ReadLine() End Sub End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output Thumb
IndexFinger
MiddleFinger
RingFinger
LittleFinger boven
22.2.2. De System.Collections.ICollection InterfaceNaast het enumeren over een collectie, is ook de mogelijkheid om het aantal elementen op te vragen of de mogelijkheid om de elementen over te kopiëren naar een array, veel gevraagd functionaliteiten voor collecties.
Dit is ondermeer waarin de ICollection interface voorziet : Public Interface ICollection : Inherits IEnumerable Sub CopyTo(ByVal array As Array, ByVal index As Integer) ReadOnly Property Count() As Integer End Interface Bemerk dat de ICollection interface overerft van de IEnumerable interface. Indien we ICollection implementeren, moeten we bijgevolg ook IEnumerable in dat type implementeren.
Een mogelijke ICollection implementatie voor een type als Hand zou er zo kunnen uitzien : Visual Basic 2010 Broncode Namespace ICollectionHand Public Class Hand : Implements ICollection Private _Items As Finger() = New Finger() { New Thumb, New IndexFinger, _ New MiddleFinger, _ New RingFinger, _ New LittleFinger} Public Function GetEnumerator() As IEnumerator _ Implements ICollection. GetEnumerator GetEnumerator = _Items.GetEnumerator() End Function Public Sub CopyTo( ByVal array As System. Array, ByVal index As Integer) _ Implements ICollection. CopyTo _Items.CopyTo(array, index) End Sub Public ReadOnly Property Count() As Integer Implements ICollection. Count Get Count = _Items.Count End Get End Property Public ReadOnly Property IsSynchronized() As Boolean _ Implements ICollection. IsSynchronized Get IsSynchronized = _Items.IsSynchronized End Get End Property Public ReadOnly Property SyncRoot() As Object _ Implements ICollection. SyncRoot Get SyncRoot = _Items.SyncRoot End Get End Property End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Om bovenstaande ICollection implementatie te vereenvoudigen is hier intern gebruik gemaakt van een Array, meer specifiek een Finger(). Omdat Array zelf reeds een ICollection is, kunnen we de implementatie van de methods GetEnumerator, CopyTo, Count, IsSynchronized en SyncRoot voor onze Hand delegeren naar de gelijknamige implementaties van de Array klasse.
Eens klasse Hand de interface ICollection implementeert kunnen instanties van deze klasse in een "collection context" gebruikt worden. Veel voorgedefinieerde collectietype bijvoorbeeld, zoals System.Collections.Queue en Stack, die overigens zelf de interface ICollection implementeren, beschikken over een constructor waar je een ICollection kan doorgeven. Dit om meteen bij creatie van dergelijke collecties een aantal initiële elementen te voorzien. Visual Basic 2010 Broncode Namespace ICollectionHand Class Client Public Shared Sub Main() Dim hand1 As ICollection = New Hand Dim queue1 As New Queue(hand1) For Each element As Object In queue1 Console.WriteLine(element) Next Console.WriteLine() Dim stack1 As New Stack(hand1) For Each element As Object In queue1 Console.WriteLine(element) Next Console.WriteLine() Dim fingersArray1(4) As Finger hand1.CopyTo(fingersArray1, 0) For Each element As Finger In fingersArray1 Console.WriteLine(element) Next Console.ReadLine() End Sub End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output Thumb
IndexFinger
MiddleFinger
RingFinger
LittleFinger
Thumb
IndexFinger
MiddleFinger
RingFinger
LittleFinger
Thumb
IndexFinger
MiddleFinger
RingFinger
LittleFinger boven
22.2.3. De System.Collections.ReadOnlyCollectionBase KlasseEenvoudiger dan het implementeren van de ICollection interface is het overerven van de abstracte ReadOnlyCollectionBase klasse.
Deze implementeert reeds de ICollection interface, wat ervoor zorgt dat wij zelf de members uit deze interface niet meer hoeven te implementeren.
De definitie van de ReadOnlyCollectionBase ziet er ongeveer zo uit : Visual Basic 2010 Broncode Namespace ReadOnlyCollectionBaseHand Public MustInherit Class ReadOnlyCollectionBase : Implements ICollection Private list As ArrayList Protected ReadOnly Property InnerList() As ArrayList Get If ( Me.list Is Nothing) Then Me.list = New ArrayList End If Return Me.list End Get End Property Public Overridable Function GetEnumerator() As IEnumerator _ Implements ICollection. GetEnumerator Return Me.InnerList.GetEnumerator End Function Private Sub CopyTo( ByVal array As Array, ByVal index As Integer) _ Implements ICollection. CopyTo Me.InnerList.CopyTo(array, index) End Sub Public Overridable ReadOnly Property Count() As Integer _ Implements ICollection. Count Get Return Me.InnerList.Count End Get End Property Private ReadOnly Property IsSynchronized() As Boolean _ Implements ICollection. IsSynchronized Get Return Me.InnerList.IsSynchronized End Get End Property Private ReadOnly Property SyncRoot() As Object _ Implements ICollection. SyncRoot Get Return Me.InnerList.SyncRoot End Get End Property End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Onze Hand ICollection kan dus een stuk eenvoudiger door van de klasse ReadOnlyCollectionBase over te erven. Visual Basic 2010 Broncode Namespace ReadOnlyCollectionBaseHand Public Class Hand : Inherits ReadOnlyCollectionBase Public Sub New() InnerList.AddRange( New Finger() { New Thumb, New IndexFinger, _ New MiddleFinger, New RingFinger, _ New LittleFinger}) End Sub End ClassEnd NamespaceNamespace ReadOnlyCollectionBaseHand Class Client Public Shared Sub Main() Dim hand1 As ICollection = New Hand Dim queue1 As New Queue(hand1) For Each element As Object In queue1 Console.WriteLine(element) Next Dim stack1 As New Stack(hand1) For Each element As Object In queue1 Console.WriteLine(element) Next Console.ReadLine() End Sub End ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output Thumb
IndexFinger
MiddleFinger
RingFinger
LittleFinger
Thumb
IndexFinger
MiddleFinger
RingFinger
LittleFinger De ReadOnlyCollectionBase klasse is voorzien om enkel-lees collecties op te baseren. Verderop bespreken we ook nog de System.Collections.CollectionBase klasse, voorzien om strongly typed editeerbare list collecties op te baseren.
Dit artikel is gepubliceerd op zondag 31 juli 2011 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.
|