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

24.1. Delegates

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.

Delegates zijn typesafe function pointers, of beter methodpointers.

Tot nu toe hadden we enkel gewerkt met pointers naar (referenties van) objecten, met delegates kunnen we dus ook pointers naar methods gaan stockeren in een delegatevariabele.  Niet alleen kunnen we die stockeren maar we kunnen die ook "invokeren", wat er op neerkomt dat die method waarnaartoe gepoint wordt, zal uitgevoerd worden.

Delegates zijn bruikbaar om in runtime pas te beslissen welke implementatie zal worden uitgevoerd (dynamical implementation).

De term "delegate" kan op een aantal manieren gebruikt worden, in onderstaand voorbeeld zien we :
- definitie van delegatetype
- declaratie van delegatevariabele/ instantie
- invokeren van een delegate (methodpointer)
"Delegate" kan dus verwijzen naar het type, naar de instantie of naar de methodpointer zelf.

Een declaratie van een delegatetype kan gebeuren op namespace, module of classniveau.

Syntax : <accessmodifier> Delegate Sub|Function <identifier> (<arguments>) <type-specifier>
Visual Basic 2012 Broncode - Codevoorbeeld 619
Option Strict On
Option Explicit On
Class Example1
    ' definitie van het delegatetype (type-safe method-pointer)
    Public Delegate Sub DelegateType()
    ' declaratie van delegate variabele die method-pointer zal bevatten
    Public Shared delegatedMethod As DelegateType
    ' method die method zal starten waar delegate variabele naartoe wijst
    Public Shared Sub StartDelegatedMethod()
        delegatedMethod.Invoke() ' of gewoon : delegatedMethod()
    End Sub
    Public Shared Sub Main()
        delegatedMethod = AddressOf TestMethod1
        StartDelegatedMethod()
        delegatedMethod = AddressOf TestMethod2
        StartDelegatedMethod()
        delegatedMethod = AddressOf TestMethod3
        StartDelegatedMethod()
        Console.ReadLine()
    End Sub
    Public Shared Sub TestMethod1()
        Console.WriteLine("test method-1")
    End Sub
    Public Shared Sub TestMethod2()
        Console.WriteLine("test method-2")
    End Sub
    Public Shared Sub TestMethod3()
        Console.WriteLine("test method-3")
    End Sub
End Class
Console Application Output
test method-1
test method-2
test method-3
Delegates kunnen dus wijzen naar procedures (Subs) of functies (Functions) en bijvoorbeeld niet naar properties, vandaar de term METHOD-pointer.

Wens je een delegate variabele op te vullen dan kan je dat door een AddressOf expressie daaraan toe te kennen.  Na AddressOf staat de identifier van de method waarvan de pointer moet gestockeerd worden.

Voluit kan je hetzelfde resultaat bereiken als je het delegatetype gaat instantiëren, en daar in de constructor de AddressOf expressie als argument gaat meegeven.
Dus : delegatedMethod = New DelegateType(AddressOf TestMethod1)
Dit kan doordat achter de schermen een delegate definitie wordt omgezet naar een class definitie.

Delegates kunnen wijzen naar instance of shared methods.
Visual Basic 2012 Broncode - Codevoorbeeld 620
Public Delegate Sub DelegateType()
Class Example2
    Public Shared delegatedMethods As DelegateType()
    Public Shared Sub StartDelegatedMethods()
        If Not delegatedMethods Is Nothing Then
            For Each delegatedMethod As DelegateType In delegatedMethods
                delegatedMethod.Invoke()
            Next
        End If
    End Sub
    Public Shared Sub Main()
        delegatedMethods = New DelegateType() {AddressOf TestMethod1, _
                                               AddressOf TestMethod2, _
                                               AddressOf TestMethod3, _
                                               AddressOf TestMethod1}
        StartDelegatedMethods()
        Console.ReadLine()
    End Sub
    Public Shared Sub TestMethod1()
        Console.WriteLine("test method-1")
    End Sub
    Public Shared Sub TestMethod2()
        Console.WriteLine("test method-2")
    End Sub
    Public Shared Sub TestMethod3()
        Console.WriteLine("test method-3")
    End Sub
End Class
Console Application Output
test method-1
test method-2
test method-3
test method-1
Hier hebben we een gelijkaardig voorbeeld, met als verschil dat de delegatetype gedefenieerd is op rootnamespaceniveau.

Dit kan dus ook, een delegatetype kan gedefinieerd worden op class-, module- of namespaceniveau.

Een ander verschil in dit voorbeeld is dat we met een array van method pointers werken.

Ook dit is geen enkel probleem zolang het we die array opvullen met pointers naar procedures (Subs) zonder argumenten, want dat is ook wat de delegatetype in zijn definitie vastlegt ("type safe").
Visual Basic 2012 Broncode - Codevoorbeeld 621
Class Example3
    Public Delegate Function ComputeMethod(ByVal number As Double) As Double
    Public Shared Sub Main()
        Dim originalNumber As Double = 10
        Dim computation1 As ComputeMethod = AddressOf GetTriple
        Dim computation2 As ComputeMethod = AddressOf GetHalf
        Dim computedNumber As Double
        computedNumber = computation1(originalNumber)                     ' (1)
        computedNumber = computation2.Invoke(computedNumber)              ' (2)
        Console.WriteLine(computedNumber)
        Console.ReadLine()
    End Sub
    Public Shared Function GetHalf(ByVal number As Double) As Double
        Return number / 2
    End Function
    Public Shared Function GetDouble(ByVal number As Double) As Double
        Return number * 2
    End Function
    Public Shared Function GetTriple(ByVal number As Double) As Double
        Return number * 3
    End Function
End Class
Console Application Output
15
Hier zien we een context-voorbeeld waarin geïllustreerd wordt waarvoor methodpointers gebruikt kunnen worden.

Alhoewel we het hier statisch in de code vastleggen zie je toch dat het grote voordeel van delegates is dat at runtime kan bepaald worden welke methods uitgevoerd moeten worden.

Je ziet hier ook nog eens dat je Invoke() impliciet (1) of expliciet (2) kan gebruiken.
Visual Basic 2012 Broncode - Codevoorbeeld 622
Class Procedure
    Public Delegate Sub TaskMethod()
    Private _Tasks As TaskMethod
    Public Sub Add(ByVal task As TaskMethod)
        _Tasks = DirectCast(System.Delegate.Combine(_Tasks, task), TaskMethod)
    End Sub
    Public Sub RemoveLast(ByVal task As TaskMethod)
        _Tasks = DirectCast(System.Delegate.Remove(_Tasks, task), TaskMethod)
    End Sub
    Public Sub RemoveAll(ByVal task As TaskMethod)
        _Tasks = DirectCast(System.Delegate.RemoveAll(_Tasks, task), TaskMethod)
    End Sub
    Public Sub RemoveFirst(ByVal task As TaskMethod)
        Dim oldTasks As System.Delegate() = _Tasks.GetInvocationList()
        Clear()
        Dim firstRemoved As Boolean = False
        For Each oldTask As TaskMethod In oldTasks
            If Not firstRemoved AndAlso oldTask.Equals(task) Then
                firstRemoved = True
            Else
                Add(oldTask)
            End If
        Next
    End Sub
    Public Sub Clear()
        _Tasks = Nothing
    End Sub
    Public Sub Start()
        If _Tasks IsNot Nothing Then _Tasks.Invoke()
    End Sub
End Class
Class Example4
    Public Shared Sub Main()
        Dim procedure1 As Procedure = New Procedure
        '
        procedure1.Add(AddressOf Task1)
        procedure1.Add(AddressOf Task2)
        procedure1.Add(AddressOf Task3)
        procedure1.Add(AddressOf Task2)
        procedure1.Add(AddressOf Task1)
        Console.WriteLine("After adding Task 1, 2, 3, 2 and 1 :")
        procedure1.Start()
        '
        procedure1.RemoveFirst(AddressOf Task2)
        Console.WriteLine("After removing first instance of Task 2 :")
        procedure1.Start()
        '
        procedure1.RemoveLast(AddressOf Task2)
        Console.WriteLine("After removing last instance of Task 2 :")
        procedure1.Start()
        '
        procedure1.RemoveAll(AddressOf Task1)
        Console.WriteLine("After removing all instances of Task 1 :")
        procedure1.Start()
        '
        procedure1.Clear()
        Console.WriteLine("After clearing all Tasks :")
        procedure1.Start()
        '
        Console.ReadLine()
    End Sub
    Public Shared Sub Task1()
        Console.WriteLine("task 1")
    End Sub
    Public Shared Sub Task2()
        Console.WriteLine("task 2")
    End Sub
    Public Shared Sub Task3()
        Console.WriteLine("task 3")
    End Sub
End Class
Console Application Output
After adding Task 1, 2, 3, 2 and 1 :
task 1
task 2
task 3
task 2
task 1
After removing first instance of Task 2 :
task 1
task 3
task 2
task 1
After removing last instance of Task 2 :
task 1
task 3
task 1
After removing all instances of Task 1 :
task 3
After clearing all Tasks :
Uit dit voorbeeld valt af te leiden dat meerdere method-pointers samen in 1 delegatevariabele gestockeerd kunnen worden.  Om dat resultaat te bereiken kan de shared method Combine() uit de System.Delegate klasse gaan gebruiken.  Deze zal ervoor zorgen dat methodpointer die je als tweede argument opgeeft gecombineerd wordt met de method-pointer(s) die als eerste argument is opgegeven.  De terugkeerwaarde van Combine() is dan weer een delegate, die we hier in dit voorbeeld gewoon in tasks kunnen stockeren.

Op analoge wijze kan je de Remove() en RemoveAll() methods van klasse System.Delegate gaan gebruiken.  Die zullen respectievelijk de laatste en alle instanties van het tweede opgeven argument (hier delegate object die naar een "task" wijst) gaan verwijderen uit de (gecombineerde) methodpointer-lijst (_Tasks).

Voor het verwijderen van de eerste instantie zie je dat we dit zelf zullen moeten implementeren.  Hiervoor is gebruik gemaakt van de GetInvocationList() method (die op alle delegate instanties aanwezig is, want overgeërfd van System.MulticastDelegate, die het opzich van System.Delegate) die ons een array oplevert van elementen van het type System.Delegate.  Deze elementen kunnen we dan gaan vergelijken in onze implementatie aan de hand van de Equals() method (ook overgeërfd, die een controle op logische gelijkheid gaat uitvoeren, logische gelijkheid is hier het wijzen naar dezelfde method).

Method GetInvocationList() levert overigens de delegates in de array in dezelfde volgorde op, als de volgorde waarop ze "gecombined" zijn.

Hieronder een ander eenvoudig context-voorbeeld waarin duidelijk wordt dat de client nu op eenvoudige wijze at runtime kan bepalen welke implementatie(s) zal worden uitgevoerd (WriteToConsole en/of WriteToFile en/of WriteToDB) als een message geschreven wordt.
Visual Basic 2012 Broncode - Codevoorbeeld 623
Class Log
    Public Delegate Sub WriteMethod(ByVal message As String)
    Private _WriteMethods As WriteMethod
    Public Sub New(ByVal writeMethod As WriteMethod)
        _WriteMethods = writeMethod
    End Sub
    Public Sub Add(ByVal writeMethod As WriteMethod)
        _WriteMethods = _
             DirectCast(System.Delegate.Combine(_WriteMethods, writeMethod),  _
                        WriteMethod)
    End Sub
    Public Sub Remove(ByVal writeMethod As WriteMethod)
        _WriteMethods = _
            DirectCast(System.Delegate.RemoveAll(_WriteMethods, writeMethod),  _
                       WriteMethod)
    End Sub
    Public Sub Write(ByVal message As String)
        If _WriteMethods IsNot Nothing Then _WriteMethods.Invoke(message)
    End Sub
End Class
Class Example5
    Public Shared Sub Main()
        Dim log1 As Log = New Log(AddressOf WriteToConsole)
        log1.Write("test1")
        '
        log1.Add(AddressOf WriteToFile)
        log1.Add(AddressOf WriteToDB)
        log1.Write("test2")
        '
        log1.Remove(AddressOf WriteToFile)
        log1.Write("test3")
        '
        Console.ReadLine()
    End Sub
    Public Shared Sub WriteToConsole(ByVal message As String)
        Console.WriteLine("writing to console : " & message)
    End Sub
    Public Shared Sub WriteToFile(ByVal message As String)
        Console.WriteLine("simulating writing to file : " & message)
    End Sub
    Public Shared Sub WriteToDB(ByVal message As String)
        Console.WriteLine("simulating writing to db : " & message)
    End Sub
End Class
Console Application Output
writing to console : test1
writing to console : test2
simulating writing to file : test2
simulating writing to db : test2
writing to console : test3
simulating writing to db : test3
Hieronder wordt expliciet geïllustreerd hoe je een delegate instantie kan laten verwijzen naar zowel een class- als instancemethod.
Visual Basic 2012 Broncode - Codevoorbeeld 624
Public Delegate Sub SomeDelegateType()
Class Example6
    Public Shared Sub Main()
        Dim someFirstInstance As SomeClass = New SomeClass With {.ID = 1}
        Dim someSecondInstance As SomeClass = New SomeClass With {.ID = 2}
        '
        Dim someDelegateInstance As SomeDelegateType
        '
        someDelegateInstance = AddressOf SomeClass.SomeClassMethod
        someDelegateInstance.Invoke()
        '
        someDelegateInstance = AddressOf someFirstInstance.SomeInstanceMethod
        someDelegateInstance.Invoke()
        '
        someDelegateInstance = AddressOf someSecondInstance.SomeInstanceMethod
        someDelegateInstance.Invoke()
        '
        Console.ReadLine()
    End Sub
End Class
Public Class SomeClass
    Public ID As Integer
    Public Sub SomeInstanceMethod()
        Console.WriteLine("SomeInstanceMethod() " & ID)
    End Sub
    Public Shared Sub SomeClassMethod()
        Console.WriteLine("SomeClassMethod()")
    End Sub
End Class
Console Application Output
SomeClassMethod()
SomeInstanceMethod() 1
SomeInstanceMethod() 2
Ook delegatedefinities kunnen geparameteriseerde types bevatten.  Dit heeft als voordeel dat men het aantal delegatetypes die moeten gedefinieerd worden, kan beperken.
Visual Basic 2012 Broncode - Codevoorbeeld 625
Delegate Function ParameterLessFunction(Of T)() As T
Delegate Function OneParameterFunction(Of ReturnType, ParameterType) _
                               (ByVal parameter As ParameterType) As ReturnType
Class Example7
    Public Shared Sub Main()
        Dim function1 As ParameterLessFunction(Of Int32) = _
                      New ParameterLessFunction(Of Int32)(AddressOf GetInteger)
        Console.WriteLine(function1.Invoke())                          ' 1
        '
        Dim function2 As ParameterLessFunction(Of String) = _
                      New ParameterLessFunction(Of String)(AddressOf GetString)
        Console.WriteLine(function2.Invoke())                          ' "text"
        '
        Dim function3 As OneParameterFunction(Of String, Int32) = _
                                  New OneParameterFunction(Of String, Int32) _
                                                (AddressOf GetStringByInteger)
        Console.WriteLine(function3.Invoke(1))                         ' "1"
        '
        Console.ReadLine()
    End Sub
    Public Shared Function GetInteger() As Integer
        GetInteger = 1
    End Function
    Public Shared Function GetString() As String
        GetString = "text"
    End Function
    Public Shared Function GetStringByInteger(ByVal parameter As Integer) As String
        GetStringByInteger = parameter.ToString()
    End Function
End Class
Console Application Output
1
text
1
Sterker nog men hoeft voor functies (met nul tot vier parameter) zelfs geen delegatetype te definiëren.  Deze zijn reeds ingebouwd (System.Func).
Visual Basic 2012 Broncode - Codevoorbeeld 626
Class Example8
    Public Shared Sub Main()
        Dim function1 As Func(Of Integer) = _
                                      New Func(Of Integer)(AddressOf GetInteger)
        Console.WriteLine(function1.Invoke())                          ' 1
        '
        Dim function2 As Func(Of String) = _
                                        New Func(Of String)(AddressOf GetString)
        Console.WriteLine(function2.Invoke())                          ' "text"
        '
        Dim function3 As Func(Of Integer, String) = _
                      New Func(Of Integer, String)(AddressOf GetStringByInteger)
        Console.WriteLine(function3.Invoke(1))                         ' "1"
        '
        Console.ReadLine()
    End Sub
    Public Shared Function GetInteger() As Integer
        GetInteger = 1
    End Function
    Public Shared Function GetString() As String
        GetString = "text"
    End Function
    Public Shared Function GetStringByInteger(ByVal parameter As Integer) _
                                                                       As String
        GetStringByInteger = parameter.ToString()
    End Function
End Class
Console Application Output
1
text
1
Hetzelfde geldt voor procedures (System.Action).
Visual Basic 2012 Broncode - Codevoorbeeld 627
Class Example9
    Public Shared Sub Main()
        Dim action1 As Action = New Action(AddressOf PrintSomething)
        action1.Invoke()
        '
        Dim action2 As Action(Of String) = _
                                  New Action(Of String)(AddressOf PrintOneThing)
        action2.Invoke("oneThing")
        '
        Dim action3 As Action(Of String, Int32) = _
                          New Action(Of String, Int32)(AddressOf PrintTwoThings)
        action3.Invoke("firstThing", 2)
        '
        Console.ReadLine()
    End Sub
    Public Shared Sub PrintSomething()
        Console.WriteLine("something")
    End Sub
    Public Shared Sub PrintOneThing(ByVal oneThing As String)
        Console.WriteLine(oneThing)
    End Sub
    Public Shared Sub PrintTwoThings(ByVal firstThing As String, _
                                     ByVal secondThing As Integer)
        Console.WriteLine(firstThing & " " & secondThing.ToString())
    End Sub
End Class
Console Application Output
something
oneThing
firstThing 2
Een generieke classmethod System.Array.ForEach(Of T) is bruikbaar om op elke element van een array (System.Array) een actie (System.Action) uit te voeren.
Deze method verwacht een arrayinstantie als eerste argument, en een System.Action instantie als tweede argument.  De System.Action instantie is een delegate instantie (method-pointer) van een generische instantie van de generieke delegateklasse (System.Action(Of T)).
Deze delegate-intantie moet wijzen naar procedure (Sub) met een argument van de actueel generische parameter gebruikt in de generische instantie.

Een generieke classfunction System.Array.ConvertAll(Of TInput, TOutput) is bruikbaar, om op basis van een array van TInput elementen, een array te bekomen van TOutput elementen.  Elk TInput element uit de source array ( eerste argument doorgeven aan ConvertAll) wordt omgezet naar een TOutput element via een function met een TInput argument die een TOutput oplevert.  Een method-pointer naar deze conversiefunctie moet worden doorgegeven als tweede argument aan de ConvertAll method.
Deze method-pointer kan gestockeerd worden in een object van een generische instantie van de generieke Converter(Of TInput, TOutput)-delegate klasse.

De generieke klasse List(Of T) (generieke versie van ArrayList) bevat gelijkaardige ForEach- en ConvertAll methods.  Een verschil is dat deze methods bij List(Of T) instancemethods zijn. Het element type waarmee een object van een generische instantie van List(Of T) wordt geparametriseerd kan meteen als parametertype voor de ForEach implementatie en als TInput type voor de ConvertAll implementatie worden gebruikt.  De ForEach method van List(Of T) hoeft dan dus ook niet generiek te zijn.
De ConvertAll method blijft generiek omdat nog steeds het TOutput type moet worden opgegeven.  De ConvertAll(Of TOutput) zal bij een List(Of T) dan ook een object van de generische instantie List(Of TOutput) opleveren.
Visual Basic 2012 Broncode - Codevoorbeeld 628
Class Person
    Public Property Name As String
    Public Overrides Function ToString() As String
        ToString = "Person : " & Name
    End Function
End Class
Class Employee
    Public Property Name As String
    Public Property Salary As Integer
    Public Overrides Function ToString() As String
        ToString = "Employee : " & Name & " " & Salary.ToString()
    End Function
    Public Function ToPerson() As Person
        ToPerson = New Person With {.Name = Name}
    End Function
    Public Shared Function ToPerson(ByVal employee As Employee) As Person
        If employee IsNot Nothing Then
            ToPerson = employee.ToPerson()
        Else
            ' throw some exception
        End If
    End Function
End Class
Class Example10
    Public Shared Sub Main()
        Dim employees1 As Employee() = New Employee() _
                       {New Employee With {.Name = "John", .Salary = 1000}, _
                        New Employee With {.Name = "Jane", .Salary = 1500}}
        Print(employees1)
        '
        System.Array.ForEach(Of Employee) _
           (employees1, New System.Action(Of Employee)(AddressOf DoubleSalary))
        ' or shorter :
        ' System.Array.ForEach(Of Employee)(employees1, AddressOf DoubleSalary)
        Print(employees1)
        '
        Dim employeesList1 As List(Of Employee) = _
                                              New List(Of Employee)(employees1)
        employeesList1.ForEach(New System.Action(Of Employee) _
                                                      (AddressOf DoubleSalary))
        ' or shorter :
        ' employeesList1.ForEach(AddressOf DoubleSalary)
        Print(employeesList1)
        '
        Dim persons1 As Person() = _
                                 System.Array.ConvertAll(Of Employee, Person) _
                                                                 (employees1, _
               New Converter(Of Employee, Person)(AddressOf Employee.ToPerson))
        ' or shorter :
        ' Dim persons1 As Person() = _
        '                         System.Array.ConvertAll(Of Employee, Person) _
        '                               (employees1, AddressOf Employee.ToPerson)
        Print(persons1)
        '
        Dim personsList1 As List(Of Person) = _
                                        employeesList1.ConvertAll(Of Person)( _
               New Converter(Of Employee, Person)(AddressOf Employee.ToPerson))
        ' or shorter :
        ' Dim personsList1 As List(Of Person) = _
        '     employeesList1.ConvertAll(Of Person)(AddressOf Employee.ToPerson)
        Print(personsList1)
        '
        Console.ReadLine()
    End Sub
    Public Shared Sub Print(ByVal enumerable As IEnumerable)
        For Each element As Object In enumerable
            Console.WriteLine(element)
        Next
        Console.WriteLine()
    End Sub
    Public Shared Sub DoubleSalary(ByVal employee As Employee)
        employee.Salary *= 2
    End Sub
End Class
Console Application Output
Employee : John 1000
Employee : Jane 1500

Employee : John 2000
Employee : Jane 3000

Employee : John 4000
Employee : Jane 6000

Person : John
Person : Jane

Person : John
Person : Jane
Aan de ForEach- en ConvertAll methods gelijkaardig zijn de methods Exists(Of T), Find(Of T), FindAll(Of T), FindIndex(Of T), FindLast(Of T), FindLastIndex(Of T) en TrueForAll(Of T).  Deze zijn generiek, waarbij het elementtype van de System.Array of List(Of T) moet worden opgegeven.
De Find* methods leveren (een) T element(en) of index op van het element of van elk element dat voldoen aan de criteria van de System.Predicate.  Objecten van een generische instantie van deze generieke System.Predicate-delegate klasse bevatten een pointer naar function met een T parameter die een Boolean opleveren.  Deze method zou moeten nagaan of het doorgegeven element (van type T) voldoet aan bepaalde criteria (en indien zo True opleveren).
Method Exists(Of T) levert True of False op naargelang een element van de System.Array of List(Of T) een element bevat die voldoen aan de door de doorgegeven System.Predicate-criteria.
Method TrueForAll(Of T) levert True of False op naargelang elk element van System.Array of List(Of T) voldoet aan de de door de doorgegeven System.Predicate-criteria.
Visual Basic 2012 Broncode - Codevoorbeeld 629
Class Example11
    Public Shared Sub Main()
        Dim employees1 As Employee() = New Employee() _
               {New Employee With {.Name = "John", .Salary = 1000}, _
                New Employee With {.Name = "Jane", .Salary = 1500}, _
                New Employee With {.Name = "Paul", .Salary = 2000}}
        '
        Dim salaryMatch As Predicate(Of Employee) = New Predicate(Of Employee) _
                                                       (AddressOf HasHighSalary)
        Dim employees2 As Employee() = _
                      System.Array.FindAll(Of Employee)(employees1, salaryMatch)
        Example10.Print(employees2)
        '
        Console.ReadLine()
    End Sub
    Public Shared Function HasHighSalary(ByVal employee As Employee) As Boolean
        If employee.Salary > 1000 Then HasHighSalary = True
    End Function
End Class
Console Application Output
Employee : Jane 1500
Employee : Paul 2000

24.1.1. Oefening

Opgave :

Vul onderstaande code aan om onderstaand programmaverloop te bekomen.

Merk op dat een aanroep naar de property CartridgeState van klasse Printer een String waarde teruggeeft zoals die gedefinieerd is in de method GetCartridgeState() van Exercise1.
Visual Basic 2012 Broncode - Codevoorbeeld 630
Class Printer
    Public Sub New(ByVal name As String)
        Me.Name = name
    End Sub
    Public Property Name As String
    Public Property InkLevel As Byte
    Public Enum CartridgeStateValue
        empty ' InkLevel = 0
        low   ' 0 < InkLevel <= 25
        half  ' 25 < InkLevel <= 75
        full  ' InkLevel > 75
    End Enum
End Class
Class Exercise1
    Public Shared Sub Main()
        Dim printer1 As Printer = New Printer("HP DeskJet 640C")
        printer1.SetActionCatridgeStateCheck(AddressOf GetCartridgeState)
        '
        printer1.InkLevel = 100
        Console.WriteLine(printer1.CartridgeState) ' Catridge is full.
        '
        printer1.InkLevel = 50
        Console.WriteLine(printer1.CartridgeState) ' Catridge is half.
        '
        printer1.InkLevel = 15
        Console.WriteLine(printer1.CartridgeState) ' Catridge is low.
        '
        printer1.InkLevel = 0
        Console.WriteLine(printer1.CartridgeState) ' Catridge is empty.
        '
        Console.ReadLine()
    End Sub
    Private Shared Function GetCartridgeState( _
                 ByVal cartridgeState As Printer.CartridgeStateValue) As String
        GetCartridgeState = "Cartridge is " & cartridgeState.ToString() & "."
    End Function
End Class
Console Application Output
Cartridge is full.
Cartridge is half.
Cartridge is low.
Cartridge is empty.
Oplossing :
Visual Basic 2012 Broncode - Codevoorbeeld 631
Partial Class Printer
    Public ReadOnly Property CartridgeState() As String
        Get
            Select Case InkLevel
                Case 0
                    CartridgeState = _
                            _GetCartridgeStateMethod(CartridgeStateValue.empty)
                Case 1 To 25
                    CartridgeState = _
                              _GetCartridgeStateMethod(CartridgeStateValue.low)
                Case 26 To 75
                    CartridgeState = _
                             _GetCartridgeStateMethod(CartridgeStateValue.half)
                Case 76 To 100
                    CartridgeState = _
                             _GetCartridgeStateMethod(CartridgeStateValue.full)
            End Select
        End Get
    End Property
    Public Delegate Function GetCartridgeStateMethodDelegate( _
                 ByVal cartridgeState As Printer.CartridgeStateValue) As String
    Private _GetCartridgeStateMethod As GetCartridgeStateMethodDelegate
    Public Sub SetActionCatridgeStateCheck( _
              ByVal getCartridgeStateMethod As GetCartridgeStateMethodDelegate)
        _GetCartridgeStateMethod = getCartridgeStateMethod
    End Sub
End Class

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