使用泛型,是否有理由创建特定的派生EventArg类
现在看起来你可以通过通用实现轻松地使用它们。
我应该去看看我的所有示例并删除我的eventArg类(StringEventArgs,MyFooEventArgs等)
public class EventArgs<T> : EventArgs
{
public EventArgs(T value)
{
m_value = value;
}
private T m_value;
public T Value
{
get { return m_value; }
}
}
答案 0 :(得分:37)
您所描述的内容基本上是tuples,用于特定目的的分组值。它们在functional programming中是一个有用的结构,并且很好地支持这种风格。
缺点是它们的值没有命名,它们需要理解上下文。 EventArgs
就其性质而言,往往远离其相关背景。因此,元组式EventArgs
可能会让消费者感到非常困惑。
假设我们有一个事件表明某个分裂已经完成,它带有分子,分母和结果:
public event EventHandler<EventArgs<double, double, double>> Divided;
事件处理程序有一些歧义:
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;
}
对于表示事件的EventArgs
,这会更清楚:
private void OnDivided(object sender, DividedEventArgs e)
{
var numerator = e.Numerator;
var denominator = e.Denominator;
var result = e.Result;
}
通用可重用EventArgs
类以牺牲表达意图为代价来简化机制的开发。
答案 1 :(得分:3)
查看Custom Generic EventArgs撰写的Matthew Cochran文章,在该文章中,他描述了如何通过两个和三个成员进一步扩展它。
使用通用EventArgs有它们的用途,当然还有它们的误用,因为类型信息在这个过程中会丢失。
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;
在下面的示例中,它是类型安全的,但更多一点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;
答案 2 :(得分:0)
正如TcK已经说过:如果您只需要传递一个值,请使用EventArgs<T>
,否则从EventArgs
(或EventArgs<T>
,无论您想要什么)派生。
答案 3 :(得分:0)
我认为Tuple风格的EventArgs非常有用。就像Tuple一样,它们可能被误用,但似乎我的懒惰比我的谨慎感更强。我实现了以下内容:
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;
}
}
可以如下使用(与event raiser extension一起使用时)
public event EventHandler<TupleEventArgs<string,string,string>> NewEvent;
NewEvent.Raise(this, TupleEventArgs.Create("1", "2", "3"));