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

26.1. Extension 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.

Types kunnen voortaan ook uitgebreid worden met extra methods (Subs of Functions) zonder dat hiervoor een afgeleide klasse wordt gecreëerd.

Zowel klassen, structures, delegates als interfaces zijn uitbreidbaar.

Deze extra methods worden "extension methods" genoemd.

Extension methods kunnen enkel in een module worden gedefinieerd.  Deze methods worden gemarkeerd met het System.Runtime.CompilerServices.Extension attribuut.

De eerste parameter van de extension method is van het type dat wordt uitgebreid.  Bij een call naar deze instancemethod wordt geen argumentwaarde voorzien voor deze eerste parameter.  De implementatie voorzien in de extension wordt uitgevoerd op de doorgespeelde instantie.
Visual Basic 2012 Broncode - Codevoorbeeld 658
Public Module PersonExtension
    <System.Runtime.CompilerServices.Extension()> _
    Public Sub Print(ByVal aPerson As Person)
        If aPerson IsNot Nothing Then
            Console.WriteLine("Istance of Person : " & aPerson.ToString())
        Else
            Console.WriteLine("No instance of Person.")
        End If
    End Sub
End Module
Public Class Person
    Public Property Name As String
    Public Overrides Function ToString() As String
        ToString = Name
    End Function
End Class
Public Class Student : Inherits Person
    Public Property ClassGroup As String
    Public Overrides Function ToString() As String
        ToString = Name & " (" & ClassGroup & ")"
    End Function
End Class
Public Class Example1
    Public Shared Sub Main()
        Dim person1 As Person = New Person With {.Name = "John"}
        Dim person2 As Person = New Student _
                                With {.Name = "Jane", _
                                      .ClassGroup = "Visual Basic"}
        Dim person3 As Person
        '
        person1.Print()                                                    ' (1)
        person2.Print()
        person3.Print()
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
Istance of Person : John
Istance of Person : Jane (Visual Basic)
No instance of Person.
Overige parameters zijn mogelijk, en fungeren dan als normale parameter voor deze method.

Onderstaande CounterExtension bevat een extension method ToString met twee parameters (1).  De tweede parameters is de te gebruiken paddingLength bij het omzetten naar een String.
De call naar deze method (3) hoeft hier enkel voor deze parameter een waarde te voorzien.

Het type Counter wordt in onderstaand voorbeeld uitgebreid met een drietal extension methods.  ToInt32 maakt het mogelijk de Counter naar een Integer om te zetten, en de twee ToString zetten om naar het String type.
Visual Basic 2012 Broncode - Codevoorbeeld 659
Public Class Counter
    Private _Value As Integer
    Public ReadOnly Property Value() As Integer
        Get
            Value = _Value
        End Get
    End Property
    Public Sub Raise()
        _Value += 1
    End Sub
    Public Sub Lower()
        _Value -= 1
    End Sub
    Public Overrides Function ToString() As String
        ToString = "Counter.Value : " & Value.ToString()
    End Function
End Class
Public Module CounterExtension
    <System.Runtime.CompilerServices.Extension()> _
    Public Function ToInt32(ByVal aCounter As Counter) As Integer
        ToInt32 = aCounter.Value
    End Function
    <System.Runtime.CompilerServices.Extension()> _
    Public Function ToString(ByVal aCounter As Counter) As String
        ToString = aCounter.Value.ToString()
    End Function
    <System.Runtime.CompilerServices.Extension()> _
    Public Function ToString(ByVal aCounter As Counter, _
                             ByVal paddingLength As Integer) As String     ' (1)
        ToString = aCounter.Value.ToString().PadLeft(paddingLength)
    End Function
End Module
Public Class Example2
    Public Shared Sub Main()
        Dim counter1 As New Counter
        counter1.Raise()
        counter1.Raise()
        '
        Dim integerValue1 As Integer = counter1.ToInt32()
        Console.WriteLine(integerValue1)
        '
        Dim stringValue1 As String = counter1.ToString()                   ' (2)
        Console.WriteLine(stringValue1)
        '
        Dim stringValue2 As String = counter1.ToString(3)                  ' (3)
        Console.WriteLine(stringValue2)
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
2
Counter.Value : 2
  2

26.1.1. Extension Method Precedence

Bemerk hoe in bovenstaand voorbeeld de call op regel (2) niet de extension method, maar de gewone instancemethod ToString aanroept.  De extension ToString is hier eenvoudigweg niet bereikbaar omdat reeds een gewone ToString bestaat.

Het kan ook voorkomen dat verschillende extension methods (met identieke signatuur) ingeladen zijn.  Ambiguïteit ontstaat bij een call naar dergelijke method(s).  Hier zal steeds de "dichtstbij-zijnde" method voorrang krijgen.

Zo zullen bijvoorbeeld extension methods uit namespace imports van het huidige broncode-document hogere prioriteit hebben dan extension methods uit namespace imports op project-niveau.

26.1.2. Extension Methods in Interfaces

Ook interfacetypes kunnen extension methods worden toegevoegd.
Visual Basic 2012 Broncode - Codevoorbeeld 660
Public Interface SomeInterface
    Sub SomeFirstMethod()
End Interface
Public Module SomeInterfaceExtension
    <System.Runtime.CompilerServices.Extension()> _
    Public Sub SomeSecondMethod(ByVal aSomeInterface As SomeInterface)
        Console.WriteLine("SomeInterface.SomeSecondMethod() implementation.")
    End Sub
End Module
Public Class SomeClass : Implements SomeInterface
    Public Sub SomeFirstMethod() Implements SomeInterface.SomeFirstMethod
        Console.WriteLine("SomeClass.SomeFirstMethod() implementation.")
    End Sub
End Class
Public Class Example3
    Public Shared Sub Main()
        Dim object1 As New SomeClass
        object1.SomeFirstMethod()
        object1.SomeSecondMethod()
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
SomeClass.SomeFirstMethod() implementation.
SomeInterface.SomeSecondMethod() implementation.
Interface bevatten normaal gezien enkel abstracte members, die niet beschikken over een bepaalde implementatie.  Het is immers niet de bedoeling in een interface te definiëren welke implemenatie wordt uitgevoerd indien deze member wordt aangeroepen.

Toch kan men interfaces enkel uitbreiden met concrete methods, die wel een implementatie bevatten.  Deze extension methods worden in een modules gedefinieerd, die enkel concrete methods kunnen bevatten.

26.1.3. Multiple Inheritance via Interfaces en Extension Methods

Als SomeInterfaceExtension (uit bovenstaand voorbeeld) ingeladen is, zal elke klasse die SomeInterface implementeert nu ook over SomeSecondMethod en bijhorende implementatie beschikken.

Dit is op zijn minst wat vreemd te noemen, gezien het implementeren van interface tot nu toe enkel een vorm van "contextual inheritance" inhield.
Vanaf heden is dit dus ook "implementation inheritance" mogelijk via het implementeren van een interface.

Gezien men meerdere interface kan implementeren, zouden liefhebbers van "multiple implementation inheritance" dit ook zo kunnen forceren.
Visual Basic 2012 Broncode - Codevoorbeeld 661
Public Interface Interface1
End Interface
Public Interface Interface2
End Interface
Public Module InterfaceExtensions
    <System.Runtime.CompilerServices.Extension()> _
    Public Sub Method1(ByVal aInterface1 As Interface1)
        Console.WriteLine("Interface1.Method1")
    End Sub
    <System.Runtime.CompilerServices.Extension()> _
    Public Sub Method2(ByVal aInterface2 As Interface2)
        Console.WriteLine("Interface2.Method2")
    End Sub
End Module
Public Class Class1 : Implements Interface1, Interface2
End Class
Public Class Example4
    Public Shared Sub Main()
        Dim object1 As New Class1
        object1.Method1()
        object1.Method2()
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
Interface1.Method1
Interface2.Method2

26.1.4. Wanneer Extension Methods Gebruiken

Extension methods zijn in hoofdzaak nuttig voor het uitbreiden van types waarvan je niet de eigenaar bent, of dus niet over de sourcecode beschikt.

Indien de klasse niet sealed/final (NotInheritable) is, dien je natuurlijk te overwegen of inheritance niet meer van toepassing is.

Extension methods gebruik je enkel indien je in een bepaalde context ( bijvoorbeeld deze van een console applicatie) een bepaalde extra functionaliteit/gedrag nodig hebt (bijvoorbeeld het printen op de console), en deze functionaliteit in andere contexten niet bruikbaar/mogelijk is.  Een windows applicatie bijvoorbeeld kan niets aan met een implementatie als Console.WriteLine(...).

Hoewel een extension method geschikt is voor het toevoegen van een instancemethod, kan je in de implementatie van deze slechts gebruik maken van de members uit de publieke interface van dat uit-te-breiden type.  De mogelijkheden in deze implementatie zijn dus beperkt, ingekapselde members kunnen immers niet benaderd worden.

Doorgaans zal een extension method in een child namespace van de klassenbibliotheek worden ondergebracht, zodoende de client van deze library de mogelijkheid te laten deze child namespace (met de extensions) al dan niet in te laden.

Bijvoorbeeld de AdministrationClassLibrary zou rechtstreeks in de namespace Administration de klasse Person kunnen definiëren.
Visual Basic 2012 Broncode - Codevoorbeeld 662
Namespace Administration
    Public Class Person
        Public Property Name As String
        Public Overrides Function ToString() As String
            ToString = Name
        End Function
    End Class
End Namespace
Naast deze klasse kan in een child namespace ConsoleExtensions de PersonExtension worden gedefinieerd.
Visual Basic 2012 Broncode - Codevoorbeeld 663
Namespace Administration
    Namespace ConsoleExtensions
        Public Module PersonExtension
            <System.Runtime.CompilerServices.Extension()> _
            Public Sub Print(ByVal aPerson As Person)
                System.Console.WriteLine(aPerson.ToString())
            End Sub
        End Module
    End Namespace
End Namespace
In een andere assembly als AdministrationConsoleApplication kan vervolgens beslist worden om de namespace Administration.ConsoleExtensions te importeren om de extensions beschikbaar te maken (1).
Visual Basic 2012 Broncode - Codevoorbeeld 664
Imports Administration.ConsoleExtensions               ' or on project-level (1)
Public Class Application
    Public Shared Sub Main()
        Dim person1 As New Administration.Person With {.Name = "John"}
        'person1.Print()                                                   ' (1)
        '
        Console.ReadLine()
    End Sub
End Class
Een windows applicatie zou deze extensions niet inladen, want deze zouden in die context niet bruikbaar zijn.

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