【C#】——委托与事件


    在大话设计模式中有一个模式叫做观察者模式,里面涉及到了委托和事件的使用。虽然在一开始学习C#的时候有接触过,但是还是很陌生,稳扎稳打,才能平步青云。所以让我们来熟悉吧!

何为委托?

    委托是对函数的封装,可以当作给方法的特征指定一个名称。委托是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为。委托对象使用的关键字delegate来声明。通俗易懂的说,委托就是用来执行方法或者函数的一个东西。
何为事件?
    事件则是委托的一种特殊形式,当发生有意义的事情时,事件对象处理通知过程。事件是说在发生其他类或对象关注的事情时,类或对象可通过事件通知它们。事件对象用event关键字声明。

下面结合实例来讲解两者的关系

class Program
    {
        static void Main(string[] args)
        {
            Cat cat=new Cat ("Tom");
            Mouse mouse1=new Mouse ("Jerry");
            Mouse mouse2=new Mouse("Jack");

            cat.CatShout +=new Cat.CatShoutEventHandler(mouse1.Run );
            cat .CatShout +=new Cat.CatShoutEventHandler (mouse2.Run );
            //表示将Mouse的Run方法通过实例化委托Cat.CatShoutEventHandler登记到Cat事件CatShout当中。

            cat.Shout ();
           
            Console.Read ();
        }
    }
    class Cat
    {
        private string name;
        public Cat(string name)
        {
            this.name = name;
        }
        public delegate void CatShoutEventHandler();
        //声明委托CatShoutEventHandle
        public event CatShoutEventHandler CatShout;
        //声明事件CatShout,它的事件类型是委托CatShoutEventHandler
        public void Shout()
        {
            Console.WriteLine ("瞄,我是{0}。",name);
            if (CatShout !=null )
            {
               CatShout ();
       //表明当执行Shout()方法时,如果CatShout中有对象登记事件,则执行CatShout()

        }
    }
    class Mouse
    {
        private string name;
        public Mouse (string name)
        {
            this.name =name;

        }
        public void Run(object sender,CatShoutEventArge args)
        {
            Console.WriteLine ("老猫{0}来了,{1}快跑!",args.Name ,name );
        }
    }
             

在这个实例中CatShoutEventHandler属于委托,CatShout属于事件。

是否有点小疑问,Cat和Mouse是怎么联系起来的?

关键点在这cat.CatShout += Cat.CatShoutEventHandler(mouse1.Run)通过CatShoutEventHandler将Mouse和Cat进行了交互绑定,当cat.CatShout被调用后,执行CatShout事件,通知老鼠猫来了,通知后该事件被委托给mouse1.Run进行处理(赶紧跑)。

添加参数


如果老鼠想要知道是哪只猫来了,又该怎么办?显然,现在委托对象必须传递必要的参数才行,这个要求也可以很容易地办到。事件的参数可以设置为任何类型的数据,在.NET框架中,还提供了事件参数基类EventArgs专门用于传递事件数据。

增加一个类CatShoutEventArgs,让它继承EventArgs,EventArgs是包含事件数据的类的基类。这个的目的就是在CatShout事件触发时,需要传递Cat对象的名字。

    

 public class CatShoutEventArge:EventArgs
    {
        private string name;
        public string Name
        {
            get {return name;}
            set { name = value; }
        }
    }

 
改写Cat类的代码,对委托CatShoutEventHandler进行重新定义。增加两个参数,第一个参数Object对象sender是指向发送通知的对象,而第二个参数CatShoutEventArgs的args,包含了所有通知者需要的附件信息,这里是老猫的名字信息。

class Cat
    {
        private string name;
        public Cat(string name)
        {
            this.name = name;
        }
        public delegate void CatShoutEventHandler(object sender,CatShoutEventArge args);
        //声明委托CatShoutEventHandle
        public event CatShoutEventHandler CatShout;
        //声明事件CatShout,它的事件类型是委托CatShoutEventHandler
        public void Shout()
        {
            Console.WriteLine ("瞄,我是{0}。",name);
            if (CatShout !=null )
            {
                CatShoutEventArge e = new CatShoutEventArge();
                e.Name = this.name;
                CatShout(this, e);
            }

        }
    }


在Mouse中改写了一点,由于有了传递过来猫的名字,所以显示的时候就可以指出老猫的名字。

 class Mouse
    {
        private string name;
        public Mouse (string name)
        {
            this.name =name;

        }
        public void Run(object sender,CatShoutEventArge args)
        {
            Console.WriteLine ("老猫{0}来了,{1}快跑!",args.Name ,name );
        }
         
Cat类中的Shout方法在触发事件CatShout之前需要判断该事件是否为null。当Cat对象的Shout方法触发事件CatShout后,必须有一个目标函数来处理这个事件,而该语句正是判断该目标函数是否存在。如果将这个判断去掉,且对事件不进行任何绑定而直接调用Shout方法,程序将在事件CatShout处弹出一个NullReferenceException的异常。
 

【总结】

使用委托使程序员可以将方法引用封装在委托对象内。然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道将调用哪个方法。两个需要存在调用关系的类型,在各自的实现中却没有编写实际的调用代码,它们只是通过一个事件和一个第三方的委托类型完成了消息的传递过程。两个类型之间不存在任何的紧密耦合,它们看似松散地通过一个委托对象中通信,实现了本书一直宣传的“高聚合”和“低耦合”观点。
 
 


评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mandy_i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值