Visual Basic .NET - Um pouco mais sobre Delegates


Neste artigo eu vou falar um pouco sobre delegates, o que são e como usá-los.

A CLR - common language runtime fornece um mecanismo de callback, também chamado de delegate, o qual são equivalentes a ponteiros de funções em outras linguagens com a vantagem de possuírem um mecanismo type-safe.

Quando você declarar um delegate em seu código o compilador VB gera uma classe derivada da classe Delegate ou MulticastDelegate e a CLR implementa todos os métodos de interesse do delegate de forma dinâmica em tempo de execução.

Nota: A classe MulticastDelegate é uma classe abstrata que contém uma lista linkada de delegates conhecida como um lista de invocação. Neste artigo tratarei somente dos Single Delegate.

Chamar um delegate é igual sintaticamente a chamar uma função, por isso, os delegates são perfeitos para implementar callbacks e eles fornecem um excelente mecanismo para desacoplar o método que esta sendo chamado em uma instância a partir do método chamador.

Na verdade o chamador do delegate não sabe ou não precisa saber se ele esta chamando uma método de instância ou um método estático(de classe) ou em qual instância ele esta chamando. O chamador pode obter uma instância do delegate e pode desacoplá-lo completamente da entidade que ele atualmente chama.

Uma declaração de delegate parece exatamente como uma declaração de método exceto por não possuir um corpo de método e possuir a palavra-chave: Delegate.

Veja abaixo um declaração para um delegate:

Public Delegate Function Teste(ByVal x As Double, ByVal y As Double) As Double

Quando o compilador encontra esta linha , ele define um tipo derivado a partir de MulticastDelegate o qual implementa um método chamado invoke que possui a mesma assinatura do método descrito na declaração do delegate.

NotInheritable Class Teste
                  Inherits System.MulticastDelegate

Public Function Invoke(ByVal x As Double, ByVal y As Double) As Double
End Function
'.........
End Class


Quando você usa um delegate você precisa vinculá-lo a um método para chamar quando ele for invocado. O método que você vincular pode ser um método de instância ou de classe (shared) mas deve possuir uma assinatura compatível com a do delegate; dessa forma os tipos de parâmetros e o tipo de retorno devem ou coincidir com a declaração do delegate ou eles devem ser convertidos implicitamente para os tipos na declaração do delegate.

O exemplo a seguir mostra uma sintaxe básica de como criar um delegate do tipo Single Delegate.

Abra o VB 2008 Express Edition e crie um novo projeto do tipo Windows Forms Application com o nome usandoDelegates;

A seguir inclua no formulário padrão form1.vb, os controles : ListBox (lstResultado) e Button (btnIniciar)conforme o leiaute abaixo:

A seguir vamos incluir o código abaixo no formulário para definir o delegate e duas rotinas que iremos usar como exemplo:

     'Definindo um delegate
    Public Delegate Sub SaudacoesDelegate(ByVal mensagem As String)

    'definindo a rotina bomDia
    Public Sub bomDia(ByVal seuNome As String)
        lstResultado.Items.Add("Olá, Bom dia " + seuNome + " !")
    End Sub
    'definindo a rotina boaNoite
    Public Sub boaNoite(ByVal seuNome As String)
        lstResultado.Items.Add("Olá, Boa noite " + seuNome + " !")
    End Sub

A linha de código abaixo define um delegate e diz para o compilador criar uma nova classe chamada SaudacoesDelegate que herda de System.Delegate:

Public Delegate Sub SaudacoesDelegate(ByVal mensagem As String)

No evento Click do botão de comando vamos incluir o código para usar o delegate:

 Private Sub btnIniciar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnIniciar.Click
        'Instanciando o delegate
        Dim minhaSaudacao As SaudacoesDelegate

        'Aqui vamos atribuir o endereço da função/rotina que desejamos encapsular para o delegate
        lstResultado.Items.Add("Incluindo uma referência da rotina 'bomDia' a um Delegate...")
        minhaSaudacao = AddressOf bomDia

        'Como atribuimos um endereço ao delegate, podemos usar o método Invoke para 
        'chamar a função no delegate Invocando um delegate
        lstResultado.Items.Add("Invocando o Delegate...")
        minhaSaudacao.Invoke("Macoratti")

        'Como o delegate somente se importa com a assinatura do método que você esta encapsulando no seu interior
        'podemos fazer uma referência a outro método
        'Atribuindo o endereço da outra função ao mesmo delegate
        lstResultado.Items.Add("Fazendo o delegate existente apontar para outra função/rotina...")
        lstResultado.Items.Add("Substituindo a referência do delegate...")
        minhaSaudacao = New SaudacoesDelegate(AddressOf boaNoite)

        'Outra forma de invocar o delegate.
        lstResultado.Items.Add("Invocando o Delegate...")
        minhaSaudacao("Macoratti")

    End Sub

Observe que na última chamada do delegate não usamos o método Invoke().

Executando o projeto iremos obter:

Lembre-se que se você tentar atribuir um endereço de um método ou função que não coincida com a declaração do delegate você irá obter um erro de compilação.

Como você pode notar os delegates são um recurso poderoso que você pode usar em seus projetos.

Em um próximo artigo irei falar sobre Multicasts Delegates que são delegates que podem apontar para múltiplas funções com a mesma assinatura, de forma que quando o método Invoke() do delegate for acionado todas as funções/rotinas inseridas no delegate serão chamadas.

Aguarde...

Eu sei é apenas VB .NET, mas eu gosto...

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ?

 

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti