Visual Basic 2012 Voorbeelden
   

visual basic 2012 broncode voorbeelden

Blijf op de hoogte van de recente aanpassingen op vbvoorbeelden!

Microsoft Visual Studio 2012Microsoft Developers Network - Visual BasicMicrosoft .NET Framework

22.8. System.Collections.CollectionBase implementeert IList

Print Email Deel op Twitter Deel op Facebook

Dit artikel is gepubliceerd op maandag 15 oktober 2012 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.

22.8.1. Eigen IList Implementaties

Een eigen implementatie van de IList interface kan eenvoudig worden opgesteld door bijvoorbeeld intern gebruik te maken van een ArrayList.  ArrayList implementeert reeds IList en beschikt dan ook reeds over implementaties van de in IList gedefinieerde members.
Door in onze implementatie van deze members te delegeren naar de gelijknamige van ArrayList vereenvoudigen we in sterke mate het werk om deze members van een implementatie te voorzien :
Visual Basic 2012 Broncode - Codevoorbeeld 535
Option Strict On

Imports System.Collections

Public Class Person
    Public Property Name As String
End Class
Namespace OwnIListImplementation
    Public Class Persons : Implements IList
        Private _Items As IList = New ArrayList
        ' IEnumerable implementation :
        Public Function GetEnumerator() As IEnumerator _
                                                Implements IList.GetEnumerator
            GetEnumerator = _Items.GetEnumerator
        End Function
        ' ICollection implementation :
        Public Sub CopyTo(ByVal array As System.Array, ByVal index As Integer) _
                                                       Implements IList.CopyTo
            _Items.CopyTo(array, index)
        End Sub
        Public ReadOnly Property Count() As Integer Implements IList.Count
            Get
                Count = _Items.Count
            End Get
        End Property
        ' IList implementation :
        Public Function Add(ByVal value As Object) As Integer _
                                                          Implements IList.Add
            Add = _Items.Add(value)
        End Function
        Default Public Overridable Property Item(ByVal index As Integer) _
                                               As Object Implements IList.Item
            Get
                Item = _Items.Item(index)
            End Get
            Set(ByVal value As Object)
                _Items.Item(index) = value
            End Set
        End Property
        '  ...
    End Class
End Namespace
Bovenstaande Persons is niet meer dan een simpele "wrapper" ( "verpakking") rond een ArrayList.  We hebben hier niet veel aan, we kunnen in clients evengoed een ArrayList object gebruiken in plaats van een Persons object.  Persons biedt niets meer dan ArrayList.

Sterker nog het heeft dezelfde nadelen als ArrayList.  Er wordt gewerkt met elementen van type Object.  De Add method verwacht een value As Object en de Item bijvoorbeeld levert een Object op.

Als het de bedoeling zou zijn deze collectie enkel voor Person items te gebruiken, dan wordt bijvoorbeeld niet at compiletime verhinderd dat men items van een ander type probeert toe te voegen (1).
Bij het raadplegen van een element via de Item property moeten we dan nog eens casten om aan de specifieke members van Person te kunnen (2).  Item leverde immers het element in Object vorm op.
Namespace OwnIListImplementation
    Public Class Client
        Public Shared Sub Main()
            Dim persons1 As New Persons
            '
            persons1.Add("dummy") ' no compile error                       ' (1)
            Console.Write(DirectCast(persons1.Item(0), Person).Name)       ' (2)
            '
            Console.ReadLine()
        End Sub
    End Class
End Namespace

22.8.2. Strongly Typed IList Implementatie

Deze nadelen kunnen we wegwerken door de publieke interface van onze wrapper aan te passen.  Door in de publieke Add method bijvoorbeeld enkel Person parameterwaardes toe te laten, maken we de list collectie - op zijn minst op het vlak van elementen toevoegen - "strongly typed" :
Namespace OwnStronglyTypedIListImplementation
    Public Class Persons : Implements IList
        '  ...
        Public Function Add(ByVal value As Person) As Integer
            '  ...
        End Function
        Private Function Add(ByVal value As Object) As Integer _
                                                            Implements IList.Add
            If TypeOf value Is Person Then
                Add = Add(DirectCast(value, Person))
            End If
        End Function
        Default Public Property Item(ByVal index As Integer) As Person
            Get
                Item = DirectCast(getItem(index), Person)
            End Get
            Set(ByVal value As Person)
                '  ...
            End Set
        End Property
        Private Property getItem(ByVal index As Integer) As Object _
                                                           Implements IList.Item
            Get
                '  ...
            End Get
            Set(ByVal value As Object)
                '  ...
            End Set
        End Property
        '   ...
    End Class
End Namespace
Nu wordt reeds at compiletime verhinderd dat wat iets anders dan een Person aan de collectie toevoegen (1) :
Namespace OwnStronglyTypedIListImplementation
    Public Class Client
        Public Shared Sub Main()
            Dim persons1 As New Persons
            '
            'persons1.Add("dummy") ' compile error                         ' (1)
            Console.Write(persons1.Item(0))                                ' (2)
            '
            Dim arrayList1 As New ArrayList
            arrayList1.Add("dummy") ' no compile error                     ' (3)
            Console.Write(DirectCast(arrayList1.Item(0), Person).Name)     ' (4)
            '
            Console.ReadLine()
        End Sub
    End Class
End Namespace
Ook het casten van een call naar Item is niet meer noodzakelijk (2), deze levert nu immers een element reeds in Person vorm op.

Ons eigen collectietype heeft nu wel voordelen op ArrayList, die zelf nog altijd in zijn publieke interface gebruik maakt van het itemtype Object.
Geen compiletime controle op itemtype (3) en meer castingoperaties (4) zijn daarvan het noodzakelijke gevolg.

Bemerk dat we nog altijd, naast de typesafe Add method, ook een implementatie voor IList.Add(value As Object) moeten voorzien.  Maar door deze implementatie in te kapselen (Private) vermijden we op zijn minst deze non typesafe method in de publieke interface.

Ook members als IndexOf, Insert, Remove en Contains zouden met parameters van type Person moeten werken, om deze collectie volledig strongly typed te maken.

22.8.3. De System.Collections.CollectionBase Klasse

Nog altijd is het vrij veel werk om in een eigen collectie de IList interface te implementeren.  Daar komt nog eens bij dat je voor elk verschillend itemtype waarvoor je een strongly typed list collectie wil dit werkt moet herhalen.
Herhalen terwijl vele members, met uitzondering van de members die noodzakelijk zijn om de collectie strongly typed te maken, waarschijnlijk op dezelfde manier geïmplementeerd worden.

Om dit werk te verlichten is reeds de System.Collections.CollectionBase klasse voorzien.  Deze is speciaal gemaakt om strongly typed list collecties op te baseren.
Type CollectionBase maakt reeds intern gebruik van een ArrayList object om de elementen in te beheren en bevat reeds de implementaties zoals Clear en RemoveAt bijvoorbeeld die voor strongly typed collecties van eender welk itemtype toch waarschijnlijk identiek zouden zijn.

Het enigste wat je nog moet naast het overerven van de members van CollectionBase, is het voorzien van typesafe members als Item, Add, IndexOf, Insert, Remove en Contains, of een subset ervan indien ze niet allemaal gewenst zijn.
Dergelijke members moeten we toevoegen omdat deze in hun signatuur gebruik moeten maken van parameters en returntypes van het specifieke itemtype waarvoor de strongly typed list collectie wordt gemaakt.

De interne ArrayList is in je eigen toe te voegen member implementaties ondermeer te benaderbaar via de ingekapselde Protected ReadOnly Property List() As IList :
Visual Basic 2012 Broncode - Codevoorbeeld 536
Namespace CollectionBaseIListImplementation
    Public Class Persons : Inherits CollectionBase
        Default Public Property Item(ByVal index As Integer) As Person
            Get
                Item = DirectCast(List.Item(index), Person)
            End Get
            Set(ByVal value As Person)
                List(index) = value
            End Set
        End Property
        Public Function Add(ByVal value As Person) As Integer
            Return List.Add(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
        Public Function Contains(ByVal value As Person) As Boolean
            Return List.Contains(value)
        End Function
    End Class
End Namespace
At compiletime wordt nu opnieuw nagegaan of we wel een item van type Person toevoegen (1).  Ook het casten van een call naar Item is niet meer noodzakelijk om de voor Person specifieke members te benaderen (2).
Visual Basic 2012 Broncode - Codevoorbeeld 537
Namespace CollectionBaseIListImplementation
    Public Class Client
        Public Shared Sub Main()
            Dim persons1 As New Persons
            '
            'persons1.Add("dummy") ' compile error                         ' (1)
            Console.Write(persons1.Item(0))                                ' (2)
            '
            Console.ReadLine()
        End Sub
    End Class
End Namespace

Dit artikel is gepubliceerd op maandag 15 oktober 2012 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.