Delegados (Visual Basic)

Los delegados son objetos que hacen referencia a métodos. Algunas veces están descritos como punteros de función con seguridad de tipos porque son parecidos a los punteros de función utilizados en otros lenguajes de programación. Sin embargo, a diferencia de los punteros a función, los delegados de Visual Basic son un tipo de referencia basado en la clase System.Delegate. Los delegados pueden hacer referencia a los dos métodos compartidos, métodos a los que se pueden llamar sin una instancia específica de una clase, y a métodos de instancia.

Delegados y eventos

Los delegados son útiles en situaciones donde es necesario un intermediario entre el procedimiento que realiza una llamada y el procedimiento que la recibe. Por ejemplo, puede que desee que un objeto que provoca eventos sea capaz de llamar a diferentes controladores de eventos bajo diferentes circunstancias. Desgraciadamente, el objeto que provoca los eventos no puede conocer de antemano qué controlador de eventos controla un evento concreto. Visual Basic permite asociar dinámicamente los controladores de eventos a eventos mediante la creación de un delegado al usar la instrucción AddHandler. En tiempo de ejecución, el delegado remite las llamadas al controlador de eventos adecuado.

Aunque puede crear sus propios delegados, en la mayoría de los casos Visual Basic crea el delegado y se ocupa de los detalles. Por ejemplo, una instrucción Event define de forma implícita una clase delegada denominada <EventName>EventHandler como clase anidada de la clase que contiene la instrucción Event, y con la misma firma que el evento. La instrucción AddressOf crea implícitamente una instancia de un delegado que hace referencia a un procedimiento concreto. Las dos líneas de código siguientes son equivalentes. En la primera línea, se ve la creación explícita de una instancia de Eventhandler, con una referencia al método Button1_Click enviada como argumento. La segunda línea es una manera más conveniente de conseguir el mismo resultado.

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

Puede utilizar el método abreviado para crear delegados en cualquier lugar donde el compilador pueda determinar el tipo de delegado por el contexto.

Declarar eventos que utilicen un tipo de delegado existente

En algunas situaciones, puede que desee declarar un evento para que utilice un tipo de delegado existente como delegado subyacente. La sintaxis siguiente describe cómo hacerlo:

Delegate Sub DelegateType()
Event AnEvent As DelegateType

Esto resulta útil cuando se desea enrutar diversos eventos hacia el mismo controlador.

Variables delegadas y parámetros

Puede utilizar delegados para otras tareas, no relacionadas con eventos, como un subprocesamiento libre o con procedimientos que necesiten llamar a diferentes versiones de funciones en tiempo de ejecución.

Por ejemplo, suponga que tiene una aplicación de anuncio clasificado que incluye un cuadro de lista con nombres de coches. Los anuncios están ordenados por títulos, que normalmente son las marcas de los coches. Un problema con el que puede encontrarse se produce cuando algunos coches incluyen el año del coche antes de la marca. El problema es que la funcionalidad de ordenación integrada del cuadro de lista ordena únicamente por códigos de carácter; primero coloca todos los anuncios que empiezan por el año y, a continuación, los anuncios que empiezan por la marca.

Para corregir este problema, puede crear un procedimiento de ordenación en una clase que utilice la ordenación alfabética estándar en la mayoría de los cuadros de lista, pero que pueda cambiar en tiempo de ejecución al procedimiento de ordenación personalizado para anuncios de coches. Para ello, pasa el procedimiento de ordenación personalizado a la clase de ordenación en tiempo de ejecución, utilizando delegados.

Expresiones AddressOf y lambda

Cada clase delegada define un constructor al cual se pasa la especificación de un método de objeto. Un argumento para un constructor delegado debe ser una referencia a un método o una expresión lambda.

Para especificar una referencia a un método, utilice la sintaxis siguiente:

AddressOf [expression.]methodName

El tipo de tiempo de compilación de expression debe ser el nombre de una clase o interfaz que contenga un método del nombre especificado cuya firma coincida con la firma de la clase delegada. methodName puede ser un método compartido o un método de instancia. Aunque se cree un delegado para el método predeterminado de la clase, methodName no es opcional.

Para especificar una expresión lambda, utilice la sintaxis siguiente:

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

En el siguiente ejemplo se muestra el uso de las expresiones AddressOf y lambda para especificar la referencia para un delegado.

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 de la función debe coincidir con la del tipo de delegado. Para obtener más información sobre las expresiones lambda, vea Lambda (expresiones) (Visual Basic). Para obtener más ejemplos de expresiones lambda y asignaciones de AddressOf a delegados, vea Conversión de delegado no estricta (Visual Basic).

Temas relacionados

Título

Descripción

Cómo: Invocar un método delegado (Visual Basic)

Proporciona un ejemplo que muestra cómo asociar un método a un delegado e invocar luego este método a través del delegado.

Cómo: Pasar procedimientos a otro procedimiento en Visual Basic

Muestra cómo utilizar los delegados para pasar un procedimiento a otro procedimiento.

Conversión de delegado no estricta (Visual Basic)

Describe cómo se pueden asignar funciones y subrutinas a delegados o controladores de eventos aunque sus firmas no sean idénticas.

Eventos (Visual Basic)

Proporciona información general sobre los eventos en Visual Basic.