|
Dit artikel is gepubliceerd op zondag 31 juli 2011 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 2010 Broncode Class Person Private m_Name As String Public Property Name() As String Get Return m_Name End Get Set( ByVal value As String) m_Name = value End Set End Property Public Overrides Function ToString() As String ToString = Name End FunctionEnd ClassClass House Private m_Number As String Public Property Number() As String Get Return m_Number End Get Set( ByVal value As String) m_Number = value End Set End Property Public Overrides Function ToString() As String ToString = Number End FunctionEnd ClassClass 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 PropertyEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
In een client kunnen we nu objecten maken van generische instanties als GenericCollection(Of Person) en GenericCollection(Of House) : Visual Basic 2010 Broncode 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 ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
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 2010 Broncode 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 ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
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 2010 Broncode 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 ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
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 2010 Broncode 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 ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
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 2010 Broncode 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 ClassEnd NamespaceDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
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 zondag 31 juli 2011 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.
|