Condividi tramite


Delegati (Visual Basic)

I delegati sono oggetti che fanno riferimento ai metodi. Vengono talvolta descritti come puntatori a funzione sicuri per tipo perché sono simili ai puntatori a funzione usati in altri linguaggi di programmazione. A differenza dei puntatori a funzione, tuttavia, i delegati di Visual Basic sono un tipo riferimento basato sulla classe System.Delegate. I delegati possono fare riferimento a entrambi i metodi condivisi, ovvero metodi che possono essere chiamati senza un'istanza specifica di una classe , e metodi di istanza.

Delegati ed eventi

I delegati sono utili nelle situazioni in cui è necessario un intermediario tra una procedura chiamante e la procedura chiamata. Ad esempio, è possibile che un oggetto che generi eventi possa chiamare gestori eventi diversi in circostanze diverse. Sfortunatamente, l'oggetto che genera gli eventi non può sapere in anticipo quale gestore eventi gestisce un evento specifico. Visual Basic consente di associare dinamicamente i gestori eventi agli eventi creando automaticamente un delegato quando si usa l'istruzione AddHandler . In fase di esecuzione, il delegato inoltra le chiamate al gestore eventi appropriato.

Anche se è possibile creare delegati personalizzati, nella maggior parte dei casi Visual Basic crea il delegato e gestisce automaticamente i dettagli. Ad esempio, un'istruzione Event definisce in modo implicito una classe delegato denominata <EventName>EventHandler come classe nidificata della classe contenente l'istruzione Event e con la stessa firma dell'evento. L'istruzione AddressOf crea in modo implicito un'istanza di un delegato che fa riferimento a una routine specifica. Le due righe di codice seguenti sono equivalenti. Nella prima riga viene visualizzata la creazione esplicita di un'istanza di EventHandler, con un riferimento al metodo Button1_Click inviato come argomento. La seconda riga è un modo più pratico per fare la stessa cosa.

AddHandler Button1.Click, New EventHandler(AddressOf Button1_Click)
' The following line of code is shorthand for the previous line.
AddHandler Button1.Click, AddressOf Me.Button1_Click

È possibile usare il modo abbreviato per creare delegati ovunque il compilatore possa determinare il tipo del delegato in base al contesto.

Dichiarazione di eventi che usano un tipo delegato esistente

In alcune situazioni, può essere necessario dichiarare un evento per usare un tipo delegato esistente come delegato sottostante. La sintassi seguente illustra come:

Delegate Sub DelegateType()
Event AnEvent As DelegateType

Ciò è utile quando si desidera instradare più eventi allo stesso gestore.

Assegnare variabili e parametri

È possibile utilizzare delegati per altre attività non correlate agli eventi, come il threading libero o con procedure che devono invocare versioni diverse di funzioni durante l'esecuzione.

Si supponga, ad esempio, di avere un'applicazione annunci classificati che includa una casella di riepilogo con i nomi delle automobili. Gli annunci vengono ordinati in base al titolo, che normalmente è la marca dell'auto. Un problema che può verificarsi è quando alcune automobili includono l'anno dell'auto prima della marca. Il problema è che la funzionalità di ordinamento predefinita della casella di riepilogo ordina solo in base ai codici carattere; posiziona tutti gli annunci che iniziano prima con le date, seguiti dagli annunci che iniziano con il make.

Per risolvere questo problema, puoi creare una routine di ordinamento in una classe che usa l'ordinamento alfabetico standard per la maggior parte delle caselle di riepilogo, ma è in grado di passare in fase di esecuzione alla procedura di ordinamento personalizzata per gli annunci di automobili. A tale scopo, passare la routine di ordinamento personalizzata alla classe di ordinamento in fase di esecuzione usando i delegati.

Espressioni AddressOf e Lambda

Ogni classe delegata definisce un costruttore a cui viene passata la specifica di un metodo di un oggetto. Un argomento di un costruttore delegato deve essere un riferimento a un metodo o a un'espressione lambda.

Per specificare un riferimento a un metodo, utilizzare la sintassi seguente:

AddressOf [expression.]methodName

Il tipo in fase di compilazione di expression deve essere il nome di una classe o di un'interfaccia che contiene un metodo con il nome specificato e la cui firma corrisponda a quella della classe delegata. methodName Può essere un metodo condiviso o un metodo di istanza. Il methodName non è facoltativo, anche se si crea un delegato per il metodo predefinito della classe.

Per specificare un'espressione lambda, usare la sintassi seguente:

Function ([parm As type, parm2 As type2, ...]) expression

Nell'esempio seguente vengono illustrate sia le espressioni AddressOf che le espressioni lambda usate per specificare il riferimento per un delegato.

Module Module1

    Sub Main()
        ' Create an instance of InOrderClass and assign values to the properties.
        ' InOrderClass method ShowInOrder displays the numbers in ascending 
        ' or descending order, depending on the comparison method you specify.
        Dim inOrder As New InOrderClass
        inOrder.Num1 = 5
        inOrder.Num2 = 4

        ' Use AddressOf to send a reference to the comparison function you want
        ' to use.
        inOrder.ShowInOrder(AddressOf GreaterThan)
        inOrder.ShowInOrder(AddressOf LessThan)

        ' Use lambda expressions to do the same thing.
        inOrder.ShowInOrder(Function(m, n) m > n)
        inOrder.ShowInOrder(Function(m, n) m < n)
    End Sub

    Function GreaterThan(ByVal num1 As Integer, ByVal num2 As Integer) As Boolean
        Return num1 > num2
    End Function

    Function LessThan(ByVal num1 As Integer, ByVal num2 As Integer) As Boolean
        Return num1 < num2
    End Function

    Class InOrderClass
        ' Define the delegate function for the comparisons.
        Delegate Function CompareNumbers(ByVal num1 As Integer, ByVal num2 As Integer) As Boolean
        ' Display properties in ascending or descending order.
        Sub ShowInOrder(ByVal compare As CompareNumbers)
            If compare(_num1, _num2) Then
                Console.WriteLine(_num1 & "  " & _num2)
            Else
                Console.WriteLine(_num2 & "  " & _num1)
            End If
        End Sub

        Private _num1 As Integer
        Property Num1() As Integer
            Get
                Return _num1
            End Get
            Set(ByVal value As Integer)
                _num1 = value
            End Set
        End Property

        Private _num2 As Integer
        Property Num2() As Integer
            Get
                Return _num2
            End Get
            Set(ByVal value As Integer)
                _num2 = value
            End Set
        End Property
    End Class
End Module

La firma della funzione deve corrispondere a quella del tipo delegato. Per altre informazioni sulle espressioni lambda, vedere Espressioni lambda. Per ulteriori esempi di espressioni lambda e AddressOf assegnazioni a delegati, vedere Conversione del delegato semplificata.

Titolo Descrizione
Procedura: Richiamare un metodo delegato Fornisce un esempio che illustra come associare un metodo a un delegato e quindi richiamare tale metodo tramite il delegato .
Procedura: Passare procedure a un'altra procedura in Visual Basic Illustra come utilizzare i delegati per passare una routine a un'altra.
Conversione rilassata del delegato Viene descritto come assegnare sotto e funzioni a delegati o gestori anche quando le firme non sono identiche
Avvenimenti Fornisce una panoramica degli eventi in Visual Basic.