para entender as diferenças, você pode olhar para estes 2 exemplos
Exemplo com delegados (ação neste caso que é um tipo de delegado que não retorna valor)
public class Animal
{
public Action Run {get; set;}
public void RaiseEvent()
{
if (Run != null)
{
Run();
}
}
}
para usar o delegado, você deve fazer algo assim
Animale animal= new Animal();
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running") ;
animal.RaiseEvent();
este código funciona bem, mas você pode ter alguns pontos fracos.
Por exemplo, se eu escrever isso
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running");
animal.Run = () => Console.WriteLine("I'm sleeping") ;
com a última linha de código que substituí os comportamentos anteriores, apenas faltando um +
(usei em +
vez de +=
)
Outro ponto fraco é que cada classe que usa sua Animal
classe pode aumentar RaiseEvent
apenas pagando animal.RaiseEvent()
.
Para evitar esses pontos fracos, você pode usar events
em c #.
Sua classe Animal mudará desta forma
public class ArgsSpecial :EventArgs
{
public ArgsSpecial (string val)
{
Operation=val;
}
public string Operation {get; set;}
}
public class Animal
{
public event EventHandler<ArgsSpecial> Run = delegate{} //empty delegate. In this way you are sure that value is always != null because no one outside of the class can change it
public void RaiseEvent()
{
Run(this, new ArgsSpecial("Run faster"));
}
}
chamar eventos
Animale animal= new Animal();
animal.Run += (sender, e) => Console.WriteLine("I'm running. My value is {0}", e.Operation);
animal.RaiseEvent();
Diferenças:
- Você não está usando uma propriedade pública, mas um campo público (com eventos, o compilador protege seus campos de acesso indesejado)
- Os eventos não podem ser atribuídos diretamente. Nesse caso, você não pode fazer o erro anterior que mostrei ao substituir o comportamento.
- Ninguém fora de sua classe pode levantar o evento.
- Os eventos podem ser incluídos em uma declaração de interface, enquanto um campo não pode
notas
EventHandler é declarado como o seguinte delegado:
public delegate void EventHandler (object sender, EventArgs e)
leva um remetente (do tipo Object) e argumentos de evento. O remetente é nulo se vier de métodos estáticos.
Você também pode usar EventHAndler
este exemplo que usaEventHandler<ArgsSpecial>
consulte aqui a documentação sobre o EventHandler