对于像我这样的初学者来说,每次看书看到Event 和Delegate的时候,就头脑发昏.往往会跳过这些章节,去阅读其他的章节,因为读这些章节需要很大的勇气,看不懂,太打击自己的学习兴趣.之前已经却步了很多次了.这次真是硬着头皮把她读完,又到Cnblogs上搜索了很多前辈的关于Event and Delegate的文章,才逐渐的有所了解. Delegate and Event是C#中很重要的概念.所以无论如何,作为net程序员,你必须要懂得,在这里我把我所理解的Delegate and Event 记录下来,希望对初学者有所帮助.
Delegate的概念
Delegate 类似于C或者C++中的指针(本人十分讨厌这句话,因为本人跟C++和C不是很熟,让自己更晕).使用Delegate我们可以封装一个方法的引用.这样我们就可以通过委托去调用我们封装的方法,而不需要知道我们具体调用了哪个方法.
很多人像我一样会问到,不使用delegate我一样可以达到同样的效果,我为什么要使用委托?OK这个问题,我也问了自己很多次了.我通过下面的这个实例来回答这个问题.
直接调用(不使用delegate)
Call a Function directly - No Delegate
using System;
using System.Collections.Generic;
using System.Text;
namespace EventAndDelegate
{
public class DelegateTest
{
public void Process()
{
Console.WriteLine("Process() begin");
Console.WriteLine("Process() end");
}
}
class Program
{
static void Main(string[] args)
{
DelegateTest myDelegate = new DelegateTest();
myDelegate.Process();
}
}
}
上面的这段代码运行的很好.但是如果我们需要在某些情况下才去Call Process()这个方法的时候,我们需要怎么样去做呢?比如我们在A(),B()方法中都需要调用这个Process()方法,你可能能想到的办法是分别在A(),B()中分别实例化DelegateTest类,然后都执行myDelegate.Process();
Code
class Program
{
static void Main(string[] args)
{
DelegateTest myDelegate = new DelegateTest();
myDelegate.Process();
//Call A
A();
//Call A
B();
}
static void A()
{
DelegateTest myDelegate = new DelegateTest();
myDelegate.Process();
}
static void B()
{
DelegateTest myDelegate = new DelegateTest();
myDelegate.Process();
}
}
这样是不是很麻烦?当然了.有没有更好的方法呢.这个时候委托就显的很重要了.我们可以把委托当作参数传递过去.就直接可以调用了
我们直接看下代码
Delegate Code
using System;
using System.Collections.Generic;
using System.Text;
namespace EventAndDelegate
{
delegate void DelegateExample();
public class DelegateTest
{
public void Process()
{
Console.WriteLine("Process() begin");
Console.WriteLine("Process() end");
}
}
class Program
{
static void Main(string[] args)
{
DelegateTest myDelegate = new DelegateTest();
//封装Process方法
DelegateExample delegateEx = new DelegateExample(myDelegate.Process);
//Call A
A(delegateEx);
//Call A
B(delegateEx);
}
static void A(DelegateExample myDelegate)
{
myDelegate();
}
static void B(DelegateExample myDelegate)
{
myDelegate();
}
}
}
当然委托的好处很多,我这里只是抛砖引玉而已.
Events
了解事件,我们知道Button是个Class,当你单击它的时候,你触发了它的Click()事件,Timer也是个Class,每一秒都在执行Tick事件.
我们通过一个实例来学习
首先定一个事件(在定义事件之前必须定一个委托)
定义委托
public delegate void NumberReachedEventHandler(object sender,NumberReachedEventArgs e);
定义事件
public event NumberReachedEventHandler NumberReached;
这样我们就准备OK了,来看下具体的Counter类
class
Program
{
static void Main(string[] args)
{
// //订阅
Counter counter=new Counter();
counter.NumberReached += new NumberReachedEventHandler(oCounter_NumberReached);
//触发
counter.CountTo(40, 12);
}
private static void oCounter_NumberReached(object sender, NumberReachedEventArgs e)
{
Console.WriteLine("Reached: " + e.ReachedNumber.ToString());
}
}
//
声明委托
public
delegate
void
NumberReachedEventHandler(
object
sender,
NumberReachedEventArgs e);
class
Counter
{
public event NumberReachedEventHandler NumberReached;
public void CountTo(int countTo, int reachableNum)
{
if (countTo < reachableNum)
throw new ArgumentException(
"reachableNum should be less than countTo");
for (int ctr = 0; ctr <= countTo; ctr++)
{
if (ctr == reachableNum)
{
NumberReachedEventArgs e = new NumberReachedEventArgs(
reachableNum);
OnNumberReached(e);
return;
}
}
}
protected virtual void OnNumberReached(NumberReachedEventArgs e)
{
if (NumberReached != null)
{
NumberReached(this, e);
}
}
}
上面的代码我们可以看出.当达到一定的数字后,就会触发OnNumberReached去触发 NumberReached(this, e)事件,可能有人要问了.为什么不直接调用 NumberReached(this, e).而是通过OnNumberReached 去间接的调用呢?很好的问题,
protected virtual void OnNumberReached(NumberReachedEventArgs e)
从OnNumberReached 的定义我们知道,protected .所以Counter的子类可以使用它.virtual Counter的子类可以重写它,这样就可以在OnNumberReached方法中做更多的事.
在上面的Main()函数中.我们通过委托,在触发counter.NumberReached 事件的时候,程序就会自动的调用oCounter_NumberReached()方法进行响应.通过事件和委托,我们可以让程序自动的去做事!
这就是委托和事件的完整的应用实例!
示例代码下载