Delegati (Visual Basic)Delegates (Visual Basic)

I delegati sono oggetti che fanno riferimento ai metodi.Delegates are objects that refer to methods. Vengono a volte descritti come puntatori a funzione indipendenti dai tipi poiché sono simili ai puntatori a funzione usati in altri linguaggi di programmazione.They are sometimes described as type-safe function pointers because they are similar to function pointers used in other programming languages. Ma a differenza dei puntatori a funzione, Visual Basic i delegati sono un tipo riferimento basato sulla classe System.Delegate.But unlike function pointers, Visual Basic delegates are a reference type based on the class System.Delegate. I delegati possono fare riferimento sia a metodi condivisi, ovvero metodi che è possibile chiamare senza una specifica istanza di una classe, sia a metodi di istanza.Delegates can reference both shared methods — methods that can be called without a specific instance of a class — and instance methods.

Delegati ed eventiDelegates and Events

I delegati sono utili nelle situazioni in cui è necessario un intermediario tra una routine chiamante e la routine chiamata.Delegates are useful in situations where you need an intermediary between a calling procedure and the procedure being called. Ad esempio, può essere necessario che un oggetto generatore di eventi sia in grado di chiamare gestori di eventi differenti in circostanze diverse.For example, you might want an object that raises events to be able to call different event handlers under different circumstances. Purtroppo, l'oggetto che genera gli eventi non può sapere in anticipo quale gestore eventi gestirà uno specifico evento.Unfortunately, the object raising the events cannot know ahead of time which event handler is handling a specific event. Visual Basic consente di associare in modo dinamico i gestori eventi con eventi mediante la creazione di un delegato quando si usa il AddHandler istruzione.Visual Basic lets you dynamically associate event handlers with events by creating a delegate for you when you use the AddHandler statement. In fase di esecuzione, il delegato inoltrerà le chiamate al gestore eventi appropriato.At run time, the delegate forwards calls to the appropriate event handler.

Sebbene sia possibile creare i delegati, nella maggior parte dei casi, Visual Basic crea automaticamente il delegato e si occupa dei dettagli per l'utente.Although you can create your own delegates, in most cases Visual Basic creates the delegate and takes care of the details for you. Un'istruzione Event, ad esempio, consente di definire implicitamente una classe delegata denominata <EventName>EventHandler come classe nidificata della classe contenente l'istruzione Event e con la stessa firma dell'evento.For example, an Event statement implicitly defines a delegate class named <EventName>EventHandler as a nested class of the class containing the Event statement, and with the same signature as the event. L'istruzione AddressOf crea in modo implicito un'istanza di un delegato che fa riferimento a una routine specifica.The AddressOf statement implicitly creates an instance of a delegate that refers to a specific procedure. Le due righe di codice seguenti sono equivalenti.The following two lines of code are equivalent. Nella prima riga è possibile osservare la creazione esplicita di un'istanza di EventHandler, con un riferimento al metodo Button1_Click inviato come argomento.In the first line, you see the explicit creation of an instance of EventHandler, with a reference to method Button1_Click sent as the argument. La seconda riga rappresenta un modo più pratico di eseguire la stessa operazione.The second line is a more convenient way to do the same thing.

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 la sintassi abbreviata per creare delegati ogni volta che il compilatore è in grado di determinare il tipo del delegato in base al contesto.You can use the shorthand way of creating delegates anywhere the compiler can determine the delegate's type by the context.

Dichiarazione di eventi che usano un tipo delegato esistenteDeclaring Events that Use an Existing Delegate Type

In alcune situazioni, è consigliabile dichiarare un evento che usa un tipo delegato esistente come delegato sottostante.In some situations, you may want to declare an event to use an existing delegate type as its underlying delegate. La sintassi seguente illustra come eseguire tale operazione:The following syntax demonstrates how:

Delegate Sub DelegateType()
Event AnEvent As DelegateType

Questa operazione si rivela utile quando si vogliono inviare più eventi allo stesso gestore.This is useful when you want to route multiple events to the same handler.

Variabili e parametri dei delegatiDelegate Variables and Parameters

È possibile usare i delegati per altre attività non relative a eventi, ad esempio il modello di threading Free, oppure con routine che richiedono la chiamata di diverse versioni delle funzioni in fase di compilazione.You can use delegates for other, non-event related tasks, such as free threading or with procedures that need to call different versions of functions at run time.

Si supponga, ad esempio, di avere un'applicazione di annunci pubblicitari che include una casella di riepilogo contenente nomi di automobili.For example, suppose you have a classified-ad application that includes a list box with the names of cars. Gli annunci sono ordinati per titolo, in genere corrispondente al modello dell'auto.The ads are sorted by title, which is normally the make of the car. Se per alcune auto il modello è preceduto dall'anno di produzione, può verificarsi un problema.A problem you may face occurs when some cars include the year of the car before the make. Il problema consiste nel fatto che la funzionalità di ordinamento integrata della casella di riepilogo esegue l'ordinamento solo in base ai codici dei caratteri, elencando prima tutti gli annunci che iniziano con una data e quindi tutti quelli che iniziano con il modello.The problem is that the built-in sort functionality of the list box sorts only by character codes; it places all the ads starting with dates first, followed by the ads starting with the make.

Per risolvere il problema, è possibile creare una routine di ordinamento in una classe che usa l'ordinamento alfabetico standard per la maggior parte delle caselle di riepilogo, ma che è in grado di passare, in fase di esecuzione, alla routine di ordinamento personalizzata per gli annunci relativi alle automobili.To fix this, you can create a sort procedure in a class that uses the standard alphabetic sort on most list boxes, but is able to switch at run time to the custom sort procedure for car ads. A questo scopo, è necessario passare la routine di ordinamento personalizzata alla classe di ordinamento in fase di esecuzione usando i delegati.To do this, you pass the custom sort procedure to the sort class at run time, using delegates.

Espressioni AddressOf e LambdaAddressOf and Lambda Expressions

Ogni classe delegata definisce un costruttore a cui viene passata la specifica di un metodo dell'oggetto.Each delegate class defines a constructor that is passed the specification of an object method. Un argomento di un costruttore di delegati deve essere un riferimento a un metodo o a un'espressione lambda.An argument to a delegate constructor must be a reference to a method, or a lambda expression.

Per specificare un riferimento a un metodo, usare la sintassi seguente:To specify a reference to a method, use the following syntax:

AddressOf [expression.]methodNameAddressOf [expression.]methodName

Il tipo in fase di compilazione dell'elemento expression deve essere il nome di una classe o un'interfaccia contenente un metodo con il nome specificato la cui firma corrisponde a quella della classe delegata.The compile-time type of the expression must be the name of a class or an interface that contains a method of the specified name whose signature matches the signature of the delegate class. Il metodo methodName può essere o un metodo condiviso o un metodo di istanza.The methodName can be either a shared method or an instance method. methodName non è un elemento facoltativo, anche se si crea un delegato per il metodo predefinito della classe.The methodName is not optional, even if you create a delegate for the default method of the class.

Per specificare un'espressione lambda, usare la sintassi seguente:To specify a lambda expression, use the following syntax:

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

Nell'esempio seguente sono illustrate sia l'espressione AddressOf che l'espressione lambda usate per specificare il riferimento per un delegato.The following example shows both AddressOf and lambda expressions used to specify the reference for a delegate.

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.The signature of the function must match that of the delegate type. Per altre informazioni sulle espressioni lambda, vedere Espressioni lambda in C++.For more information about lambda expressions, see Lambda Expressions. Per altri esempi di espressioni lambda e assegnazioni di AddressOf a delegati, vedere Conversione di tipo relaxed del delegato.For more examples of lambda expression and AddressOf assignments to delegates, see Relaxed Delegate Conversion.

TitoloTitle DescrizioneDescription
Procedura: Richiamare un metodo delegatoHow to: Invoke a Delegate Method Viene offerto un esempio che mostra come associare un metodo a un delegato e quindi richiamare tale metodo tramite il delegato.Provides an example that shows how to associate a method with a delegate and then invoke that method through the delegate.
Procedura: Passare una routine a un'altra routine in Visual BasicHow to: Pass Procedures to Another Procedure in Visual Basic Viene illustrato come usare i delegati per passare una routine a un'altra routine.Demonstrates how to use delegates to pass one procedure to another procedure.
Conversione di tipo relaxed del delegatoRelaxed Delegate Conversion Viene descritto come assegnare subroutine e funzioni a delegati o gestori anche quando le relative firme non sono identiche.Describes how you can assign subs and functions to delegates or handlers even when their signatures are not identical
EventiEvents Viene offerta una panoramica degli eventi in Visual Basic.Provides an overview of events in Visual Basic.