La relajación de delegados es otra de las nuevas características del lenguaje VB.NET (9.0) (que ya venía incluida en la versión 2.0 del lenguaje C#). 

Un poco de historia para contextualizar esta característica:

Como todos sabemos, un delegado no es sino un puntero que hace referencia a una dirección de memoria que contiene la firma de un método (y el método en sí). En versiones anteriores (podríamos ir directamente al lenguaje C++ para comprobar esto) la firma del método era fuerte (strong). Eso quiere decir que el método espero un numero determinado de parámetros y espera que cada uno de éstos parámetros sea de un tipo específico y, finalmente, devolverá un objeto de un tipo concreto (o no devolverá nada). Ejemplo:

Public Sub DoSomething(ByVal Param1 As String, ByVal Param2 As StringDictionary)

Los delegados nacieron como una via para envolver la firma de un método, de forma que se podía comprobar, antes de llamar a un método, que a éste se le pasaban los parámetros adecuados (tanto en número como en tipos). 

Imaginemos la siguiente situación:

Como es bien sabido, todos los tipos de objetos del .NET Framework derivan de la clase Object . Imaginemos, pues, que, haciendo uso de la OO, decidimos realizar la siguiente operación:

 

Imports System.Runtime.CompilerServices
Imports System.Collections.Specialized

Public Class TryRelaxedDelegates

    Private Delegate Sub DoSomething(ByVal Param1 As String, ByVal Param2 As StringDictionary)

    Public Sub ProbarDelegado()
        Dim delegado As New DoSomething(AddressOf HacerAlgo)
        delegado(New Object, New Object)
    End Sub

    Private Sub HacerAlgo(ByVal str As String, ByVal strdic As StringDictionary)

        Console.WriteLine(“OK!”)

    End Sub

End Class

 

¿qué ocurrirá? Pues la verdad es que la respuesta, a dia de hoy, será: Depende

– Si utilizamos una versión de C# (entendiendo que el código anterior debería traducirse a C#) anterior a la versión 2.0 o utilizamos VB.NET 8.0 o anterior, esta operación nos dará un error de compilación, puesto que los parámetros que le hemos pasado a la función no se corresponden con la firma del delegado y, por lo tanto, se producirá un error de compilación.

– Sin embargo, si utilizamos C# 2.0 o posterior o bien Vb.NET 9.0, esta operación (la mostrada en el código, dónde estamos pasando Object’s en vez de objetos con el tipo esperado) está permitida. Esto es gracias a la relajación de delegados . Ahora se habilita la posibilidad de utilizar, no solo lo objetos que indica la firma del método, sino también todos aquellos que estén dentro de la misma herencia de clases (contravarianza). Así pues, imaginemos que tenemos la siguiente estructura de clases:

Gracias a la relajación de delegados, podríamos declarar un delegado que apuntara al siguiente método:

Public Function ObtenerNombreDoctor(ByVal Doctor As Doctor) As String

y llamarlo de las siguientes formas:

Dim doc As New Doctor (“Román”)
Dim per As New Persona (“Alberto”)
Dim obj As Object 

 – ObtenerNombreDoctor(doc) –> Funciona, ya que cumple con la firma del método
 – ObtenerNombreDoctor(per) –> Funciona, gracias a la relajación de delegados y a la contravarianza
 – ObtenerNombreDoctor(obj) –> Lo mismo que en el caso anterior
 – ObtenerNombreDoctor() –> También funciona (en VB.NET) ya que la relajación llega al extremo de no tener que indicar ningún parámetro. 

Pues bien, eso es todo en cuanto a la relajación de delegados (Relaxed delegates). Como siempre, espero volver a veros por aquí!😉