adszone.org
venerdì 20 settembre 2024
"Il modo corretto di pensare il software"
home
consulenza  vb.net  contatti 
  Visual Basic .NET
  Delegates
Domande

Delegates

Scusate la presentazione del codice, cosi' a bruciapelo, ma a volte e' bene affrontare la dura realta' gia' dai primi momenti.

    Dim count As Integer

    Delegate Sub Display()
    Dim ptrDisplay As New Display(AddressOf Display_Decimale) 

    Private Sub Display_Decimale()
        Label1.Text = "Decimale: " & count
    End Sub

    Private Sub Display_Binario()
        Dim n As Integer = count
        Dim s As String = "" 
        Do 
           s = IIf(n Mod 2 = 1, "1", "0")  & s 
           n = n  \ 2 
        Loop While n <>  0
        Label1.Text = "Binario: " & s
    End Sub

    Private Sub Display_Esadecimale()
        Dim n As Integer = count, v As Integer
        Dim s As String = "" 
        Do v = n Mod 16 
            Select
                Case v Case 0 To 9
                    s =  Chr(v + Asc("0")) & s
                Case 10 To 15
                    s = Chr((v - 10) + Asc("A")) & s 
            End Select
            n = n  \ 16 
        Loop While n <>  0
        Label1.Text = "Esadecimale: " & s
    End Sub

    Private Sub Form1_Load(ByVal sender As Object, _
            ByVal e As System.EventArgs) Handles MyBase.Load
        count = 0
        optDecimale.Checked = True
        Timer1.Interval = 1000
        Timer1.Enabled = True
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles Timer1.Tick
        ptrDisplay() 'oppure ptrDisplay.Invoke()
        count = (count + 1) Mod 16
    End Sub

    Private Sub optDeciamle_CheckedChanged(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles optDecimale.CheckedChanged
        ptrDisplay = AddressOf Display_Decimale 
    End Sub

    Private Sub optBinario_CheckedChanged(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles optBinario.CheckedChanged
        ptrDisplay = AddressOf Display_Binario 
    End Sub

    Private Sub optEsadecimale_CheckedChanged(ByVal sender As System.Object, 
            ByVal e As System.EventArgs) Handles optEsadecimale.CheckedChanged
        ptrDisplay = AddressOf Display_Esadecimale 
    End Sub

Eh si', i puntatori, in linguaggi come il C o C++ non sono mai stati digeriti facilmente da nessuno. Forse sara' per la loro estrema semplicita', chissa'. In effetti un puntatore, in quei linguaggi, altro non e' che un indirizzo di memoria. Insoddisfatti? Cosa volete di piu'? Il loro campo di applicazione, ovviamente.

Lo scopo dell'esempio e' di mostrare un contatore su un Form che s'incrementi da 0 a 15 e poi ricominci. Tre RadioButton indicano in che tipo di formato numerico visualizzare il conteggio, decimale, binario o esadecimale. Alla pressione dei tre pulsanti, cambiamo la procedura display da utilizzare ed il gioco e' fatto. Ciascuna trasformera' il valore del contatore nel formato che le compete. Ecco i controlli da inserire sul form:

Controllo Text Name
RadioButton Decimale optDecimale
RadioButton Binario optBinario
RadioButton Esadecimale optEsadecimale
Label "" Label1
Timer -- Timer1

Cos'hanno in comune gli elementi del codice evidenziati in rosso? Tutti definiscono lo stesso prototipo di procedura. Sono Sub e non richiedono parametri. Si dice che hanno lo stesso tipo di Signature. Chiaramente il nome cambia. Tra tutti, il Delegate ha qualcosa di particolare, assomiglia ad una procedura, ma non ha corpo. Avendo, pero', la stessa Signature delle altre, puo' fare da loro segnalibro, cioe' identificare una di esse. E' potenzialmente un riferimento alle altre tre procedure, quello che in altri linguaggi verrebbe detto puntatore. Ma, a differenza dei puntatori, esso e' una particolare classe gestita dal compilatore.

Come ogni classe, anche per il Delegate dobbiamo creare un'istanza. Lo facciamo nella prima riga marcata in blu. Il suo costruttore prende proprio un indirizzo, al quale la classe, in seguito, si potra' riferire. Cosi' creiamo l'istanza ptrDisplay associandogli l'indirizzo di Display_Decimale. Vi ricordo che possiamo fare tutto cio' proprio perche' il Delegate ha la stessa Signature del metodo in questione.

Ricapitolando, abbiamo dichiarato un Delegate e lo abbiamo istanziato. Ora possiamo utilizzarlo. Lo facciamo nella riga verde. Notate che il suo impiego assomiglia all'invocazione di un normale metodo. Come vi aspetterete, la riga verde eseguira' il metodo Display_Decimale. Questo perche' tale metodo e' stato associato nel costruttore. Ora pero', se esaminate le altre righe blue in fondo, vedete che cambiamo l'associazione dinamicamente. A seconda dell'evento, ne facciamo una diversa. Tutto cio' non vi fa' pensare ad un interrutore a piu' vie, detto anche switch?

		
                      Display_Decimale	
                             | 
                             | 
        counter ----> ptrDisplay --- Display_Binario
                             | 
                             | 
                      Display_Esadecimale
                      
Ultimo aggiornamento 13/01/2004