Conversión de delegado flexible

Actualización: noviembre 2007

La conversión de delegado flexible, incluida en Visual Basic 2008, permite asignar funciones y subrutinas a delegados o controladores de eventos cuando sus firmas no son idénticas. Por tanto, el enlace a los delegados se vuelve coherente con el enlace ya permitido en las llamadas a métodos. 

Parámetros y tipo de valor devuelto

En lugar de la coincidencia exacta de firmas, la conversión flexible requiere que se cumplan las condiciones siguientes cuando Option Strict está establecido en On:

  • Debe existir una conversión de ampliación desde el tipo de datos de cada parámetro delegado al tipo de datos del parámetro correspondiente de la función asignada o Sub. En el ejemplo siguiente, el delegado Del1 tiene un parámetro, Integer. El parámetro m en las expresiones lambda asignadas debe tener un tipo de datos para el que haya una conversión de ampliación desde Integer, como Long o Double.

    ' Definition of delegate Del1.
    Delegate Function Del1(ByVal arg As Integer) As Integer
    
    ' Valid lambda expression assignments with Option Strict on or off:
    
    ' Integer matches Integer.
    Dim d1 As Del1 = Function(m As Integer) 3
    
    ' Integer widens to Long
    Dim d2 As Del1 = Function(m As Long) 3
    
    ' Integer widens to Double
    Dim d3 As Del1 = Function(m As Double) 3
    

    Sólo se permiten las conversiones de restricción cuando Option Strict está establecido en Off.

    ' Valid only when Option Strict is off:
    
    Dim d4 As Del1 = Function(m As String) CInt(m)
    Dim d5 As Del1 = Function(m As Short) m
    
  • Debe existir una conversión de ampliación en la dirección contraria desde el tipo de valor devuelto de la función o Sub asignada al tipo de valor devuelto del delegado. En los ejemplos siguientes, el cuerpo de cada expresión lambda asignada se debe evaluar como un tipo de datos que se amplía a Integer, porque el tipo de valor devuelto de del1 es Integer.

    ' Valid return types with Option Strict on:
    
    ' Integer matches Integer.
    Dim d6 As Del1 = Function(m As Integer) m
    
    ' Short widens to Integer.
    Dim d7 As Del1 = Function(m As Long) CShort(m)
    
    ' Byte widens to Integer.
    Dim d8 As Del1 = Function(m As Double) CByte(m)
    

Si Option Strict está establecido en Off, se quita la restricción de ampliación en ambas direcciones.

' Valid only when Option Strict is set to Off.

' Integer does not widen to Short in the parameter.
Dim d9 As Del1 = Function(n As Short) n

' Long does not widen to Integer in the return type.
Dim d10 As Del1 = Function(n As Integer) CLng(n)

Omisión de las especificaciones del parámetro

Los delegados flexibles también permiten omitir completamente las especificaciones del parámetro en el método asignado:

' Definition of delegate Del2, which has two parameters.
Delegate Function Del2(ByVal arg1 As Integer, ByVal arg2 As String) As Integer
' The assigned lambda expression specifies no parameters, even though
' Del2 has two parameters. Because the assigned function in this 
' example is a lambda expression, Option Strict can be on or off.
' Compare the declaration of d16, where a standard function is assigned.
Dim d11 As Del2 = Function() 3

' The parameters are still there, however, as defined in the delegate.
Console.WriteLine(d11(5, "five"))

' Not valid.
' Console.WriteLine(d11())
' Console.WriteLine(d11(5))

Observe que no puede especificar algunos parámetros y omitir otros.

' Not valid.
'Dim d12 As Del2 = Function(p As Integer) p

La capacidad de omitir parámetros es útil en una situación en la que se define un controlador de eventos, donde están implicados varios parámetros complejos. No se usan argumentos en algunos controladores de eventos. En su lugar, el controlador tiene directamente acceso al estado del control en el que se registra el evento y omite los argumentos. Los delegados flexibles permiten omitir argumentos en aquellas declaraciones sin ambigüedades. En el ejemplo siguiente, el método completo OnClick se puede volver a escribir como RelaxedOnClick.

Sub OnClick(ByVal sender As Object, ByVal e As EventArgs) Handles b.Click
    MessageBox.Show("Hello World from" + b.Text)
End Sub

Sub RelaxedOnClick() Handles b.Click
    MessageBox.Show("Hello World from" + b.Text)
End Sub

Ejemplos de AddressOf

Las expresiones lambda se usan en los ejemplos anteriores para que se vean fácilmente las relaciones entre tipos. Sin embargo, se permite la misma flexibilidad para las asignaciones de delegado que usan AddressOf, Handles o AddHandler.

En el siguiente ejemplo, las funciones f1, f2, f3 y f4 se pueden asignar a Del1.

' Definition of delegate Del1.
Delegate Function Del1(ByVal arg As Integer) As Integer
' Definitions of f1, f2, f3, and f4.
Function f1(ByVal m As Integer) As Integer
End Function

Function f2(ByVal m As Long) As Integer
End Function

Function f3(ByVal m As Integer) As Short
End Function

Function f4() As Integer
End Function
' Assignments to function delegate Del1.

' Valid AddressOf assignments with Option Strict on or off:

' Integer parameters of delegate and function match.
Dim d13 As Del1 = AddressOf f1

' Integer delegate parameter widens to Long.
Dim d14 As Del1 = AddressOf f2

' Short return in f3 widens to Integer.
Dim d15 As Del1 = AddressOf f3

El ejemplo siguiente sólo es válido cuando Option Strict está establecido en Off.

' If Option Strict is Off, parameter specifications for f4 can be omitted.
Dim d16 As Del1 = AddressOf f4

' Function d16 still requires a single argument, however, as specified
' by Del1.
Console.WriteLine(d16(5))

' Not valid.
'Console.WriteLine(d16())
'Console.WriteLine(d16(5, 3))

Colocar valores devueltos de una función

La conversión de delegado flexible permite asignar una función a un delegado Sub, omitiendo así el valor devuelto de la función. Sin embargo, no se puede asignar un Sub a un delegado de función. En el ejemplo siguiente, la dirección de función doubler se asigna al delegado SubDel3.

' Definition of Sub delegate Del3.
Delegate Sub Del3(ByVal arg1 As Integer)

' Definition of function doubler, which both displays and returns the
' value of its integer parameter.
Function doubler(ByVal p As Integer) As Integer
    Dim times2 = 2 * p
    Console.WriteLine("Value of p: " & p)
    Console.WriteLine("Double p:   " & times2)
    Return times2
End Function
' You can assign the function to the Sub delegate:
Dim d17 As Del3 = AddressOf doubler

' You can then call d17 like a regular Sub procedure.
d17(5)

' You cannot call d17 as a function. It is a Sub, and has no 
' return value.
' Not valid.
'Console.WriteLine(d17(5))

Vea también

Tareas

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

Cómo: Escribir controladores de eventos

Conceptos

Expresiones lambda

Conversiones de ampliación y de restricción

Los delegados y el operador AddressOf

Inferencia de tipo de variable local

WithEvents y la cláusula Handles

Referencia

Option Strict (Instrucción)