Tenho percebido que para muitas pessoas o uso de Delegados (ou Delegates e Eventos não está muito claro.
Bom então vamos á uma breve explicação sobre este assunto.
Em C# os delegados são objetos de primeira classe, totalmente suportados pela linguagem, um delegado é um tipo de referência usado para encapsular um método como uma assinatura e um tipo de retorno específico. Você pode encapsular QUALQUER método usando um delegate, mas o método deve coincidir com o delegate usado.
Criamos um delegado com a palavra-chave delegate seguida de um tipo de retorno e a assinatura dos métodos que podem ser delegados a ela, conforme abaixo:
public delegate int delegateInteiro();
Está declaração define um delegado chamado delegateInteiro, que encapsulará quaisquer método que retorne um inteiro.
Uma vez definindo o delegado, você pode encapsular um método-membro com ele, instanciando-o e passando um método que coincida com o tipo de assinatura.
Acho que já deu para termos uma idéia de como um delegate funciona, agora vamos falar um pouco sobre os Eventos.
Os eventos em C# são introduzidos junto com os delegados. Por convenção, os manipuladores de eventos do .NET Framework retornam void e recebem dois parâmetros. O primeiro parâmetro é a ‘fonte’ do evento (ou seja, o objeto que faz a públicação). O segundo parâmetro é um objeto derivado do EventArgs. É recomendável que seus manipuladores de eventos sigam esse padrão.
O EventArgs é a classe que serve de base para todos os dados de evento. A assinatura de um evento é parecido com este abaixo:
public event delegateInteiro eventoInteiro;
Bom agora vamos criar um programa que simula uma passagem de tempo, Ao iniciar nosso exercício, adicione o namespace System.Threading, com ele iremos simular um intervalo de tempo e ver os dias passarem como se fosse em um passe de mágica.
A estrutura de nossa aplicação ficará assim:
// Abaixo estamos criando nossa classe de eventos, para ser usado posteriormente em nossa aplicação. public class MeuEventArgs : EventArgs { public readonly int _dia; public readonly int _mes; public readonly int _ano; public MeuEventArgs(int dia, int mes, int ano) { this._dia = dia; this._mes = mes; this._ano = ano; } }
Iremos criar uma Estrutura com DIA MÊS E ANO.
struct structData { public int dia; public int mes; public int ano; }
Para podermos gerar nossa passagem de tempo, vamos implementar a classe que realmente fará isso.
public class PassagemDeTempo { // Note que estamos iniciando o mes com o valor 11 e o ano com o valor 1900. private int _dia; private int _mes = 11; private int _ano = 1900; private structData _data = new structData(); // Declaramos nosso delegado para encapsular os metodos. public delegate void PassagemDeTempoHandler(object sender, MeuEventArgs e); // Nosso evento, onde passaremos nosso delegado com seu método encapsulado. public event PassagemDeTempoHandler OnPassagemDeTempo; // Iniciando a passagem de tempo. public void IniciarPassagem() { for (;;) { // Aqui estamos dando um intervalo de ½ seg. para podermos ver essa passagem Thread.Sleep(500); // Gerando os dias,meses e anos e abastecendo nossa estrutura _data.mes = gerarMes(_mes); _data.dia = gerarDias(_dia); _data.ano = gerarAno(_ano); Sempre que passar um dia chamaremos nosso evento. if (_data.dia != _dia) { MeuEventArgs eve = new MeuEventArgs(_data.dia, _data.mes, _data.ano); if (OnPassagemDeTempo != null) { OnPassagemDeTempo(this, eve); } } this._dia = _data.dia; this._mes = _data.mes; this._ano = _data.ano; } } // os metodos abaixo são apenas tratamentos. private int gerarDias(int dia){ if (dia >= 31) return 1; return ++dia; } private int gerarMes(int mes){ if (_dia >= 31) { if (mes >= 12) return 1; return ++mes; } else return mes; } public int gerarAno(int ano) { if (_mes == 12 && _dia == 31) return ++ano; else return ano; } } // Aqui em nossa classe MostrarPassagemDeTempo que exibimos os dias passando. public class MostrarPassagemDeTempo { public void Subscribers(PassagemDeTempo _tempo) { //Arqui estamos encapsulando a funcao que mostra a passagem de tempo. // note que estamos abastecendo um evento. _tempo.OnPassagemDeTempo += new PassagemDeTempo.PassagemDeTempoHandler(Mostrar); } public void Mostrar(object sender,MeuEventArgs e) { Console.WriteLine("{0}/{1}/{2}", e._dia, e._mes, e._ano); } } }
Para finalizar em nosso MAIN apenas escreveremos 4 linha de código:
PassagemDeTempo PassTmp = new PassagemDeTempo(); MostrarPassagemDeTempo MosPassTmp = new MostrarPassagemDeTempo(); MosPassTmp.Subscribers(PassTmp); PassTmp.IniciarPassagem();
Execute o programa e verá como é fácil! 🙂
Até a próxima pessoal.