Este é um post disponível para assinantes MVPDesmitificando delegates - Artigo .net Magazine 84
Este artigo trata de um poderoso recurso oferecido pelo .Net Framework, chamado delegate. A ideia deste artigo é abordar este tema de forma clara, simplificada e prática tendo como objetivo a apresentação das vantagens significativas que este recurso oferece no desenvolvimento de sistemas.
[Artigo já está disponível no Leitor Digital DevMedia®. Clique aqui para acessá-lo]
> Clique aqui para ler todos os artigos da .net Magazine 84
O tipo delegate nos permite encapsular a referência de um método dentro de um objeto e este mesmo objeto pode ser transferido entre chamadas através das classes de uma aplicação para ser invocado em algum outro ponto do programa, desta forma não se sabendo em tempo de compilação qual método será invocado. Simplificando esta ideia inicial, por exemplo, pode-se encapsular um método dentro de um objeto e passar este objeto como argumento entre chamadas de métodos e em algum determinado ponto do código resgatar esta referência e invocar o método pelo qual o delegate foi inscrito. Assim o comportamento de execução do método será realizado de acordo com sua referência assinada.
Delegates possuem estreita ligação com a estrutura de métodos e é declarado com as mesmas características de um método, possuem valor de retorno e parâmetros. Uma importante observação é que para inscrever um método através de um delegate, a declaração do método e do delegate devem ser compatíveis. Se um método tem como retorno um tipo inteiro e dois parâmetros de entrada do tipo string o delegate que irá representá-lo em uma chamada anônima deverá possuir uma estrutura idêntica, caso contrário o código fonte não irá compilar.
O conceito de delegate se originou na ideia de função para ponteiros que é bastante difundida dentro do universo C/C++. Uma relevante e considerável melhoria que o .Net trouxe em relação aos ponteiros para função do C/C++ não gerenciado é a vantagem dos delegates serem tipos seguros, pois as funções para ponteiros são representadas apenas pelo endereço em memória e não dizem nada a respeito da quantidade de parâmetros ou tipos e valor de retorno. Com isso, se em tempo de desenvolvimento o programador se equivocar na declaração destas estruturas, este erro somente será descoberto em tempo de execução e não se tem como prever o comportamento da execução deste código. Já não é assim com os delegates, pois possuem uma estrutura de metadados bem definida que descreve seus atributos, não acontecendo o cenário citado anteriormente.
Declarando e acionando delegates
Delegate é um tipo que é composto por modificador de acesso que determina sua visibilidade, o identificador reservado delegate, tipo de retorno, nome e parâmetros de entrada. Uma vez declarado um delegate, é permitido ao desenvolvedor criar instâncias deste tipo assim como é feito em uma classe. Em seu construtor padrão é obrigatória a passagem de um parâmetro que referencia um método estático ou dinâmico. A referência da declaração de um delegate define uma classe que é derivada da classe System.MulticastDelegate e desta forma é herdado seus métodos e propriedades, com isso a partir destes métodos pode-se acionar o delegate de diferentes formas. Uma modalidade que é interessantíssima e muito útil é a chamada assíncrona.
Chamadas síncronas e assíncronas
Em uma chamada síncrona a um método, o processamento do código chamador (thread) é bloqueado enquanto o método chamado executa seu processamento e ao final desta chamada o método retorna ao código chamador que prossegue adiante. Este modelo de chamada em muitas situações se torna indesejável, principalmente em aplicações de interface com usuário, pois causa a impressão de que o sistema travou e sobre certas circunstâncias o sistema operacional pode informar ao usuário que o sistema parou de responder. Quando uma chamada assíncrona é realizada o retorno ao método chamador é imediato e um processamento paralelo é iniciado. Ao contrário de uma chamada síncrona o processamento do método chamador não é bloqueado, com isto se um retorno é esperado deste processamento assíncrono será necessário estabelecer meios para sincronização deste processamento.
A construção de operações síncronas é a forma natural e comum de realizar chamadas a métodos dentro do desenvolvimento de aplicações, no entanto para se realizar chamadas assíncronas é necessário expressar programaticamente isso. Para atingir este objetivo o desenvolvedor tem a opção de construir sua própria lógica de controle e sincronismo ou contar com o suporte dos delegates que oferecem suporte a este tipo de funcionalidade promovendo e facilitando muito a vida do programador. De uma forma muita simples isso pode ser realizado, basta o desenvolvedor, após ter declarado um delegate e criado uma instância, chamar o método BeginInvoke. Neste instante o .Net Framework se encarregará de estabelecer um processamento paralelo e caso seja necessário receber a notificação de término deste processamento, pode-se passar como argumento um método que será invocado automaticamente após a conclusão deste processamento assíncrono. O retorno da chamada ao método BeginInvoke é um objeto construído sobre a interface IAsyncResult que permite controle sobre a chamada assíncrona, tal como bloquear o processamento corrente e aguardar o processamento assíncrono. Outra forma de aguardar pelo processamento assíncrono é chamar o método EndInvoke passando o resultado da chamada do BeginInvoke. Estas são formas de controles que o desenvolvedor tem para sincronizar o resultado desta chamada com outras operações dentro de uma lógica de aplicação.
Delegação
Delegação pode ser entendida como o ato de transferir poder e responsabilidade a outros, assim como acontece em muitas situações do cotidiano em que há a incumbência de realizar determinadas tarefas por outras pessoas. Entende-se que quem delega, ao transferir a responsabilidade espera somente o resultado, muitas vezes não interferindo na forma como a tarefa é executada. Com isso em mente é possível entender o conceito de delegate dentro do .NET, pois ao declarar um delegate se cria uma estrutura que será representada por uma codificação ainda não determinada e que será inscrita por um ou mais métodos posteriormente.
Um conceito muito importante no design de projetos de sistemas é a separação de responsabilidades e com o auxílio de delegates é facilmente empregável estas ideias. Imaginando um método dentro de uma classe que irá apresentar o resultado de um cálculo qualquer, este método deve apenas apresentar o resultado e não se importar como este cálculo será realizado. Dentro deste escopo pode-se passar como argumento para este método um delegate que será responsável por representar o método pelo qual o cálculo será feito. No primeiro exemplo prático isso será melhor exemplificado.
Multicast delegates
Conforme já mencionado anteriormente, no momento da criação de uma nova instância de um delegate é necessário atribuir como argumento um método em seu construtor padrão e quando o delegate for acionado este método será executado. Entretanto os delegates não estão restritos somente a execução de um método apenas, é possível atribuir mais de um método a um delegate através do operador += e através do método GetInvocationList do delegate obter a lista de métodos associados a ele para iterar sobre a coleção de métodos associados. Caso a assinatura do método tenha retorno void, basta simplesmente acionar a execução do delegate e todos os métodos associados serão executados sequencialmente. Esta capacidade de execução múltipla de métodos é denominada multicast delegate.
Primeiro exemplo - Declarando delegates
Um pequeno exemplo do uso de delegates é utilizado para esclarecer a sintaxe e em seguida um segundo exemplo mais completo fará uso de uma aplicação do tipo Windows Forms que conterá um gráfico de barras que será atualizado cada vez que alguma operação DML ocorrer em uma tabela no banco de dados SQL Server.
A Listagem 1 mostra o primeiro exemplo onde há uma classe chamada Presentation que contém o método Show que é responsável pela apresentação de cálculos matemáticos. Na linha 33 foi declarado o delegate chamado Calc que tem como retorno um tipo decimal e recebe como parâmetro um array do mesmo tipo de seu retorno. Este delegate declarado na linha 33 é utilizado como primeiro parâmetro do método Show na linha 35. Na linha 37 uma estrutura de repetição foreach itera sobre a coleção de delegates obtida através do método GetInvocationList e em seguida na linha 38 em cada referência de delegate é acionado o método Invoke e passado os argumentos. Ainda na linha 38 a execução do delegate traz como retorno um valor do tipo decimal que é formatado dentro de uma string para apresentação através do método WriteLine da classe Console.
ATENÇÃO! A exibição deste artigo foi interrompida.
Este é um post disponível para assinantes MVP
9 COMENTÁRIOS
Atenciosamente,
Equipe Devmedia.

// Código completo disponível no download do artigo
Onde faço o download deste artigo ?
No entanto, você pode baixar os códigos fontes dessa revista através do seguinte link: http://www.devmedia.com.br/post-20416-Revista--net-Magazine-Edicao-84.html
Atenciosamente,
Equipe Devmedia.
44 {
45 //Código completo disponível no download do artigo
46 }
Onde faz o "download" do artigo?
Na página indicada no post anterior tem o indice dos artigos da edição, eu abro ele e venho pra página onde está escrito esse código....

Atenciosamente,
Equipe Devmedia.
Space do autor



1
0
