para entender las diferencias puedes mirar estos 2 ejemplos
Ejemplo con delegados (acción en este caso que es un tipo de delegado que no devuelve valor)
public class Animal
{
public Action Run {get; set;}
public void RaiseEvent()
{
if (Run != null)
{
Run();
}
}
}
para usar el delegado debes hacer algo como esto
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 bien, pero podría tener algunos puntos débiles.
Por ejemplo si escribo esto
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running");
animal.Run = () => Console.WriteLine("I'm sleeping") ;
con la última línea de código había anulado los comportamientos anteriores solo con uno faltante +
(he usado en +
lugar de +=
)
Otro punto débil es que cada clase que usa tu Animal
clase puede subir RaiseEvent
simplemente llamándola animal.RaiseEvent()
.
Para evitar estos puntos débiles, puede utilizar events
en c #.
Tu clase de Animal cambiará de esta manera
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"));
}
}
llamar eventos
Animale animal= new Animal();
animal.Run += (sender, e) => Console.WriteLine("I'm running. My value is {0}", e.Operation);
animal.RaiseEvent();
Diferencias:
- No está utilizando una propiedad pública sino un campo público (con eventos, el compilador protege sus campos del acceso no deseado)
- Los eventos no se pueden asignar directamente. En este caso, no puede hacer el error anterior que mostré al anular el comportamiento.
- Nadie fuera de tu clase puede plantear el evento.
- Los eventos se pueden incluir en una declaración de interfaz, mientras que un campo no
notas
EventHandler se declara como el siguiente delegado:
public delegate void EventHandler (object sender, EventArgs e)
toma un remitente (de tipo Objeto) y argumentos de evento. El remitente es nulo si proviene de métodos estáticos.
También puede usar EventHAndler
en su lugar este ejemplo que usaEventHandler<ArgsSpecial>
consulte aquí para obtener documentación sobre EventHandler