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

23.16. Generieke Methods

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.

Ook methods op zich kunnen werken met type parameters (voor datatype van de argumenten of terugkeerwaarde), men spreekt in dit geval over "generic methods".  Hierbij kan de aanroepende code op basis van zen vereisten het juiste datatype voorzien.

Een method wordt niet generiek door het te definiëren in een generieke container (class, interface, structure of delegate).  Om generiek te zijn moet de method op zen minst over een typeparameter beschikken.  Niet generieke klassen bijvoorbeeld kunnen dus beschikken over generieke methods, en generieke klassen kunnen beschikken over niet generieke methods.

Veronderstel onderstaande itemtypes Person en House en de generieke collectie GenericCollection(Of T) :
Visual Basic 2012 Broncode - Codevoorbeeld 613
Class Person
    Public Property Name As String
    Public Overrides Function ToString() As String
        ToString = Name
    End Function
End Class
Class House
    Public Property Number As String
    Public Overrides Function ToString() As String
        ToString = Number
    End Function
End Class
Class GenericCollection(Of T) : Inherits Collections.CollectionBase
    Public Sub Add(ByVal item As T)
        List.Add(item)
    End Sub
    Default Public ReadOnly Property Item(ByVal index As Integer) As T
        Get
            Item = List.Item(index)
        End Get
    End Property
End Class
In een client kunnen we nu objecten maken van generische instanties als GenericCollection(Of Person) en GenericCollection(Of House) :
Visual Basic 2012 Broncode - Codevoorbeeld 614
Namespace Example1
    Class Client
        Public Shared Sub Main()
            Dim persons1 As New GenericCollection(Of Person)
            Dim houses1 As New GenericCollection(Of House)
            '
            persons1.Add(New Person With {.Name = "John"})
            persons1.Add(New Person With {.Name = "Jane"})
            '
            houses1.Add(New House With {.Number = "1"})
            houses1.Add(New House With {.Number = "2"})
        End Sub
    End Class
End Namespace
Stel dat we in clients de collectie objecten wensen om te zetten naar arrays van elementen van het itemtype.  Dan kunnen we hiervoor een utility schrijven, die we dan als volgt wensen te gebruiken :
Visual Basic 2012 Broncode - Codevoorbeeld 615
Namespace Example2
    Class Client
        Public Shared Sub Main()
            Dim persons1 As New GenericCollection(Of Person)
            Dim houses1 As New GenericCollection(Of House)
            '
            persons1.Add(New Person With {.Name = "John"})
            persons1.Add(New Person With {.Name = "Jane"})
            '
            houses1.Add(New House With {.Number = "1"})
            houses1.Add(New House With {.Number = "2"})
            '
            Dim persons2 As Person() = CollectionConverter.ToArray(persons1)
            Dim houses2 As House() = CollectionConverter.ToArray(houses1)
            '
            For Each person As Person In persons2
                Console.WriteLine(person.Name)
            Next
            '
            For Each house As House In houses2
                Console.WriteLine(house.Number)
            Next
            '
            Console.ReadLine()
        End Sub
    End Class
End Namespace
Een probleem is echter dat de CollectionConverter.ToArray(persons1)-call een Person() moet opleveren, maar de CollectionConverter.ToArray(houses1) een House() moet opleveren.
Eén method heeft echter slechts één bepaald returntype.  We kunnen dit oplossen door minstens twee ToArray methods te definiëren : ToArray(collection As GenericCollection(Of Person)) As Person() en ToArray(collection As GenericCollection(Of House)) As House().
Visual Basic 2012 Broncode - Codevoorbeeld 616
Namespace Example2
    Class CollectionConverter
        Public Shared Function ToArray(ByVal collection As  _
                                       GenericCollection(Of Person)) As Person()
            Dim array(collection.Count - 1) As Person
            For index As Integer = 0 To collection.Count - 1
                array(index) = collection(index)
            Next
            ToArray = array
        End Function
        Public Shared Function ToArray(ByVal collection As  _
                                         GenericCollection(Of House)) As House()
            Dim array(collection.Count - 1) As House
            For index As Integer = 0 To collection.Count - 1
                array(index) = collection(index)
            Next
            ToArray = array
        End Function
    End Class
End Namespace
Console Application Output
John
Jane
1
2
Elke keer we een GenericCollections van een ander actueel parametertype naar een strong typed arrays wensen om te zetten, moeten dan een nieuwe ToArray definiëren.

Een meer dynamische oplossing zou erin bestaan generieke method ToArray(Of T) As T() te definiëren :
Visual Basic 2012 Broncode - Codevoorbeeld 617
Namespace Example3
    Class CollectionConverter
        Public Shared Function ToArray(Of T) _
                            (ByVal collection As GenericCollection(Of T)) As T()
            Dim array(collection.Count - 1) As T
            For index As Integer = 0 To collection.Count - 1
                array(index) = collection(index)
            Next
            ToArray = array
        End Function
    End Class
    Class Client1
        Public Shared Sub Main()
            Dim persons1 As New GenericCollection(Of Person)
            Dim houses1 As New GenericCollection(Of House)
            '
            persons1.Add(New Person With {.Name = "John"})
            persons1.Add(New Person With {.Name = "Jane"})
            '
            houses1.Add(New House With {.Number = "1"})
            houses1.Add(New House With {.Number = "2"})
            '
            Dim persons2 As Person() = CollectionConverter.ToArray(persons1)
            Dim houses2 As House() = CollectionConverter.ToArray(houses1)
            '
            For Each person As Person In persons2
                Console.WriteLine(person.Name)
            Next
            '
            For Each house As House In houses2
                Console.WriteLine(house.Number)
            Next
            '
            Console.ReadLine()
        End Sub
    End Class
End Namespace
Console Application Output
John
Jane
1
2
Merk op hoe in bovenstaande client er geen actuele parameter wordt opgegeven bij het aanroepen van de generieke method.

De compiler zal in bovenstaand geval proberen het gepaste datatype als actuel parameter type zelf in te vullen.  Dit wordt ook wel "type inference" genoemd.  In bovenstaand situatie zal gezien het actuele parametertype van de expressies persons1 en houses1, House en Person is, de compiler veronderstellen dat Person en House de actueel parametertypes zijn voor de calls naar de functie ToArray(Of T).

Indien de compiler er niet in slaagt om een gepast datatype te vinden, wordt een fout gegenereerd.

Type inference kan enkel indien geen enkele actuele parameter wordt opgegeven, indien meerdere parameters bestaan voor de generieke method (wat ook mogelijk is), moet men dus ofwel alle, ofwel geen enkele actuele parameter worden opgeven.  Enkel indien geen enkele actuele parameter is opgegeven zal type inference worden toegepast.

Men mag natuurlijk altijd afzien van deze type inference door expliciet het actueel parametertype op te geven :
Visual Basic 2012 Broncode - Codevoorbeeld 618
Namespace Example3
    Class Client2
        Public Shared Sub Main()
            Dim persons1 As New GenericCollection(Of Person)
            Dim houses1 As New GenericCollection(Of House)
            '
            persons1.Add(New Person With {.Name = "John"})
            persons1.Add(New Person With {.Name = "Jane"})
            '
            houses1.Add(New House With {.Number = "1"})
            houses1.Add(New House With {.Number = "2"})
            '
            Dim persons2 As Person() = _
                                CollectionConverter.ToArray(Of Person)(persons1)
            Dim houses2 As House() = _
                                  CollectionConverter.ToArray(Of House)(houses1)
            '
            For Each person As Person In persons2
                Console.WriteLine(person.Name)
            Next
            '
            For Each house As House In houses2
                Console.WriteLine(house.Number)
            Next
            '
            Console.ReadLine()
        End Sub
    End Class
End Namespace
Console Application Output
John
Jane
1
2
Voor de volledigheid moeten we hier vermelden dat het creëren van dergelijke GenericCollection(Of T) en CollectionConverter niet noodzakelijk is.
De voorgedefinieerde List(Of T) bijvoorbeeld beschikt reeds over een method ToArray() As T().

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