学习然后整理头绪:委托和事件
发布成“文章”,应该只会出现在我的博客里,而不会在首页的“随笔分类”里出现,这样就不会误导比我还菜的人了,虽然我认为本文没有太大的错误。。。
对于“委托和事件”,我确实很无奈,很多次尝试拿下它,每次都放弃了。这几天刚好有空,一定要攻克下来!
学习的时候,主要参考了张子阳写的经典:C# 中的委托和事件 以及它的续。
例子就是无数人都写过的那个热水器。
马上就停电了,赶快整理一下头绪,然后等拉电看动漫>.<
刚才写的时候我不能肯定会成功运行,所以就简化了来做,节约时间嘛。
public class Heater
{
public string type = "高性能的热水器";
public class boiledEventArgs : EventArgs
{
public readonly int _temp;
public boiledEventArgs(int temp)
{
_temp = temp;
}
}
public delegate void boiledEventHandler(object sender, boiledEventArgs e);
public event boiledEventHandler boiled;
//该方法是用于调用事件的,也可以不用该方法,直接在BoileWater()中调用事件
public void OnBoiled(boiledEventArgs e)
{
if (boiled != null)
{
boiled(this,e);
}
}
public void BoileWater()
{
for (int i =0; i < 101; i++)
{
if (i > 94)
{
boiledEventArgs e = new boiledEventArgs(i);
OnBoiled(e);
}
}
}
}
//警告
public class Alert
{
public void MakeAlert(object sender, Heater.boiledEventArgs e)
{
Heater ht = (Heater)sender;
Console.WriteLine("this is alert type:{0}",ht.type);
Console.WriteLine("this is alert temperature {0}",e._temp);
}
}
class Program
{
static void Main(string[] args)
{
Heater he = new Heater();
Alert al = new Alert();
he.boiled += al.MakeAlert;
he.BoileWater();
Console.Read();
}
}
委托和事件该这样写
public delegate void boiledEventHandler(object sender, boiledEventArgs e);
public event boiledEventHandler boiled;
要注意委托的签名,应该和“显示器”以及“报警器”里的方法一致,在我这里,就是要和Class Alert里的public void MakeAlert(object sender, Heater.boiledEventArgs e)一致。
换句话说,因为在运行的时候,Heater类里的boiled事件要绑定Alert类里的MakeAlert方法,
所以,boiled事件对应的委托,即boiledEventHandler,该委托的签名要和MakeAlert()方法一致。
据说有种东西叫“协变逆变”,我不懂,这里也不讨论。。。
运行的时候,先绑定“警告”方法到HT的boiled事件,然后执行HT中的主要方法,即“烧水”!
在“烧水”执行的过程中,需要判断:如果水温到达65℃,那么马上执行OnBoiled方法,当然啦,需要将当前温度传递给它。
在这里,温度被封装在了一个类里面,这个类就是“boiledEventArgs : EventArgs”。我觉得啊,这个类里面可以封装更多的东西。这样,就可以一次性传递很多信息了。
在OnBoiled方法中,调用了boiled事件,并传递给它(object sender, boiledEventArgs e),这和该事件对应的委托的签名一致。
该sender就是Heater的实例,在这里,就是he;
e就是之前传递给OnBoiled方法的那个e,它是一个类的实例。
boiled事件在获取了足够的参数以后,就查找它到底绑定了那些方法,然后按顺序开始执行那些方法。
哦,我补充说明一下,
1,我觉得,肯定是要验证委托的签名是否和方法的一致,虽然不清楚到底什么时候验证,但肯定是要验证的。
2,执行那些绑定的方法之前,肯定是要把有关的数据传递给被执行的方法的吧,例如Alert类的MakeAlert(object sender, Heater.boiledEventArgs e)方法需要两个参数,不传递参数的话怎么能够执行呢,呵呵。
当然,在HEATER类的主方法“烧水”里,可以直接调用boiled事件,然后把OnBoiled方法去掉,一样可以成功运行。
只是,正如我看的资料上说的,约定了调用事件的方法要以“On”开头嘛,就像btn1_OnClick一样。另外,OnBoiled和“烧水”分离开,也不错啊,可以不“烧水”而直接调用该方法。
不过,区别是明显的:
由于“烧水”里采用了循环,所以每次温度改变,都会调用OnBoiled方法,最终调用boiled事件绑定的方法,产生一系列的输出。
而直接调用OnBoiled方法的话,最终只能调用一次绑定的方法,产生一次输出。而且还需要自己实例化一个Heater.boiledEventArgs e,并为它赋值。
快拉电了,等来电了再说吧。