c# - uso - tipos de genericos
¿Son necesarias las clases EventArg ahora que tenemos genéricos? (4)
Con los genéricos, ¿hay alguna razón para crear clases derivadas de EventArg específicas?
Parece que ahora puedes usarlos sobre la marcha con una implementación genérica.
¿Debo ir a través de todos mis ejemplos y eliminar mis clases eventArg (StringEventArgs, MyFooEventArgs, etc.)?
public class EventArgs<T> : EventArgs
{
public EventArgs(T value)
{
m_value = value;
}
private T m_value;
public T Value
{
get { return m_value; }
}
}
Como TcKs ya dijo: Use EventArgs<T>
si solo necesita pasar un valor, de lo contrario derivar de EventArgs
(o EventArgs<T>
, lo que quiera).
Lo que está describiendo son esencialmente tuplas , valores agrupados utilizados para un propósito particular. Son una construcción útil en programación funcional y admiten ese estilo muy bien.
La desventaja es que sus valores no tienen nombre, y requieren que se entienda el contexto. EventArgs
por su propia naturaleza a menudo se consume lejos de su contexto relevante. Por lo tanto, EventArgs
tuple-esque puede ser muy confuso para el consumidor.
Digamos que tenemos un evento que indica que se ha completado una división, y lleva el numerador, el denominador y el resultado:
public event EventHandler<EventArgs<double, double, double>> Divided;
El controlador de eventos tiene cierta ambigüedad:
private void OnDivided(object sender, EventArgs<double, double, double> e)
{
// I have to just "know" this - it is a convention
var numerator = e.Value1;
var denominator = e.Value2;
var result = e.Value3;
}
Esto sería mucho más claro con un EventArgs
representa el evento:
private void OnDivided(object sender, DividedEventArgs e)
{
var numerator = e.Numerator;
var denominator = e.Denominator;
var result = e.Result;
}
Las clases genéricas EventArgs
reutilizables facilitan el desarrollo del mecanismo a expensas de expresar el intento.
Mire el artículo sobre Custom Genérico EventArgs escrito por Matthew Cochran , en ese artículo describe cómo expandirlo aún más con dos y tres miembros.
El uso de EventArgs genéricos tiene sus usos y, por supuesto, sus usos incorrectos, ya que la información de tipo se pierde en el proceso.
public class City {...}
public delegate void FireNuclearMissile(object sender, EventArgs<City> args);
public event FireNuclearMissile FireNuclearMissileEvent;
public delegate void QueryPopulation(object sender, EventArgs<City> args);
public event QueryPopulation QueryPopulationEvent;
En el siguiente ejemplo, es seguro, pero un poco más LOC:
class City {...}
public class FireNuclearMissileEventArgs : EventArgs
{
public FireNuclearMissileEventArgs(City city)
{
this.city = city;
}
private City city;
public City City
{
get { return this.city; }
}
}
public delegate void FireNuclearMissile(object sender, FireNuclearMissileEventArgs args);
public event FireNuclearMissile FireNuclearMissileEvent;
public class QueryPopulationEventArgs : EventArgs
{
public QueryPopulationEventArgs(City city)
{
this.city = city;
}
private City city;
public City City
{
get { return this.city; }
}
}
public delegate void QueryPopulation(object sender, QueryPopulationEventArgs args);
public event QueryPopulation QueryPopulationEvent;
Creo que los EventArgs de estilo Tuple son útiles. Al igual que Tuple, pueden ser mal utilizados, pero parece que mi pereza es más fuerte que mi sentido de la precaución. Implementé lo siguiente:
public static class TupleEventArgs
{
static public TupleEventArgs<T1> Create<T1>(T1 item1)
{
return new TupleEventArgs<T1>(item1);
}
static public TupleEventArgs<T1, T2> Create<T1, T2>(T1 item1, T2 item2)
{
return new TupleEventArgs<T1, T2>(item1, item2);
}
static public TupleEventArgs<T1, T2, T3> Create<T1, T2, T3>(T1 item1, T2 item2, T3 item3)
{
return new TupleEventArgs<T1, T2, T3>(item1, item2, item3);
}
}
public class TupleEventArgs<T1> : EventArgs
{
public T1 Item1;
public TupleEventArgs(T1 item1)
{
Item1 = item1;
}
}
public class TupleEventArgs<T1, T2> : EventArgs
{
public T1 Item1;
public T2 Item2;
public TupleEventArgs(T1 item1, T2 item2)
{
Item1 = item1;
Item2 = item2;
}
}
public class TupleEventArgs<T1, T2, T3> : EventArgs
{
public T1 Item1;
public T2 Item2;
public T3 Item3;
public TupleEventArgs(T1 item1, T2 item2, T3 item3)
{
Item1 = item1;
Item2 = item2;
Item3 = item3;
}
}
Se puede usar de la siguiente manera (cuando se usa con una extensión de evento )
public event EventHandler<TupleEventArgs<string,string,string>> NewEvent;
NewEvent.Raise(this, TupleEventArgs.Create("1", "2", "3"));