委托与事件——C#版本

Posted 杨思默

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了委托与事件——C#版本相关的知识,希望对你有一定的参考价值。

什么是委托与事件

  委托是对函数的封装,可以当作给方法的特征指定一个名称。而事件则是委托的一种特殊形式,当发生有意义的事情时,事件对象处理通知过程。
  委托是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为

为什么要用委托与事件

  用例子来说明为什么必须要用委托与事件。

V1_猫叫老鼠跑,依赖:

public class Client
	public static void main(string[] args)
		Cat cat = new Cat("Tom");
		cat.Shout();
	



public class Cat
	private string name;
	public Cat(string name)
		this.name = name;
	
	public void Shout()
		Console.WriteLine("喵,我是0",name);
		Mouse mouse = new Mouse("Jerry");
		mouse.Run();
	


public class Mouse
	private string name;
	public Mouse(string name)
		this.name = name;
	
	public void Run()
		Console.WriteLine("猫来了,0快跑",name);
	

以上代码对应类图:

  在V1中,由图可以明显的看出来,猫直接依赖了老鼠。但咱们结合现实生活来看,猫和老鼠是与生俱来的天敌,他们互不认识,但只要猫一出现,老鼠肯定会跑。所以前提是猫不认识老鼠,但老鼠听到猫叫会跑。那咱们的代码写的就有问题了,在猫类的猫叫方法中直接实例化了老鼠类,表示猫认识老鼠,猫叫是通知老鼠跑的意思,直接产生了猫叫老鼠跑关系。如何解开这种关系,此时就引入了委托与事件,让我们拭目以待!

V2_猫叫老鼠跑,事件与委托:

public class client
	public static void main(string[] args)
		Cat cat = new Cat("Tom");
		Mouse mouse = new Mouse("Jerry");
		CatShout += new cat.CatShoutEventHandler(mouse.run);
		cat.Shout();
		Console.Read();
	 


public class Cat
	private string name;
	public Cat(string name)
		this.name=name;
	
	public delegate void CatShoutEventHandler();
	public event CatShoutEventHandler CatShout;
	public void Shout()
		Console.WriteLine("喵,我是0",name);
		if(CatShout != null)
			CatShout();
		
	


public class Mouse
	private string name;
	public Mouse(string name)
		this.name=name;
	
	public void Run()
		Console.WriteLine("猫来了,0快跑",name);
	

以上代码对应类图:

  在类图中,我们可以明显的看出猫和老鼠类没有关系了,实际上他们是通过委托与事件产生了联系。在主函数中CatShout += new cat.CatShoutEventHandler(mouse.run);表示将Mouse的Run方法通过实例化委托Cat.CatShoutEventHandler 登记到Cat的事件CatShout当中。其中“+=”表示“add CatShout”的意思。解决了我们第一版代码出现的问题,对猫和老鼠进行了解耦合操作。

事件与委托概念和V2_猫叫老鼠跑代码做映射:

  为了让大家能更清楚的认识到委托与事件,我做了一个概念对应代码的分析,供大家理解:
将此句对应上代码:委托是对函数的封装,可以当作给方法的特征指定一个名称。而事件则是委托的一种特殊形式,当发生有意义的事情时,事件对象处理通知过程。

  1. 委托是对函数的封装:Cat.CatShoutEventHandler (mouse1.Run);——将老鼠跑的方法封装到了CatShoutEventHandler委托中。
  2. 可以当作给方法的特征指定一个名称:CatShoutEventHandler;——在声明委托CatShoutEventHandler时已经确定了,可以根据业务随意起名。
  3. 事件则是委托的一种特殊形式:public event CatShoutEventHandler CatShout;
  4. 当发生有意义的事情时:if(CatShout != null)——如果此事件里登记了委托,才会继续执行
  5. 事件对象处理通知过程:CatShout();——自我调用,此时去执行事件,触发老鼠跑。

将此句对应上代码:委托是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为

  1. 委托是一种引用方法的类型:public delegate void CatShoutEventHandler();
  2. 一旦为委托分配了方法,委托将与该方法具有完全相同的行为:Cat.CatShoutEventHandler (mouse1.Run)

  学无止境,我们不仅需要能写出符合业务的代码,还要写出和实际相符合的代码来,我们需要不断地练习实践才可能真正成为优秀的软件工程师!

C#委托与事件

  写在前面:新手学车,误撞轻拍!

一.关于委托,在刚开始看的时候心中一直有着这样几个疑问:

  1.什么是委托?

  2.委托有存在的必要吗?

  3委托的作用和特点究竟在哪里?

  看了很多讲解,翻了很多书,整理出如下实例

 

二.什么是委托?

  委托在C#里的意义和在现实里差不多,从字面意思理解即可。举个例子:领导委托小张去传递个文件,这就是委托。

  而在C#中同样是这样的道理。只是整个动作中有两个对象,施加委托者和委托承担者是两个对象而不是人而已。

  委托的代码写法:

        public delegate void MessageManager();

  和方法的写法差不多,只是内部没有实际处理代码。

  delegate是委托的关键词,这个就是介于施加委托者和委托承担者的委托关系处理关键。

 

三.举例说话

  举个例子,某公司领导Manager有件关于代码处理的工作(Coding)需要委托个下属小张(MrZhang)去做。

  a.下面看领导(Manager)和小张(MrZhang)的内部动作代码,下面是

        public delegate void MessageManager();

  上面是施加委托者的方法代码。

  b.下面看小张(MrZhang)的内部代码:

public class MrZhang
    {
       public static void Coding()
        {
            MessageBox.Show("小张Coding已完成");
        }
}

  小张本身含有能完成Coding工作的能力。

  c.下面看委托部分了,领导如何委托给小张。

            MessageManager Manager = new MessageManager(MrZhang.Coding);
         Manager();

  MessageManager Manager = new MessageManager(MrZhang.Coding);

  这是委托的具体动作,要做的动作是Coding,而这件事儿委托给MrZhang来做了。

  1.委托的方法必须要加上,因为委托的构造函数是不为空的。

  2.委托的参数和返回类型,都要和你要具体委托的方法要一致

  然后开始执行Manager();

  d.整体代码如下,读者可以复制到工程尝试下:

 

 public class MainWindow
{ 
delegate void MessageManager();

        public MainWindow()
        {
            InitializeComponent();
            MessageManager Manager = new MessageManager(MrZhang.Coding);
            Manager();
        }
}
 public class MrZhang
    {
       public static void Coding()
        {
            MessageBox.Show("小张Coding已完成");
        }
     }

  e.委托事件可以同时委托给多个对象,如下:

  public MainWindow()
        {
            InitializeComponent();
            MessageManager Manager = new MessageManager(MrZhang.Coding);
            //通过+=绑定委托
            Manager += new MessageManager(MrLiu.Coding);
            Manager();

            //通过-=解绑
       Manager -= new MessageManager(MrLiu.Coding);
}

  可以通过+=同时将委托给多个对象,也可以通过-=将已委托给对象的事件解绑。

 

 四.传参委托

   注意:这个是我自己理解出来之后为了简单易懂命名的,重在讨论和明白,看着觉得误导的就忽略这个词吧。

  在写代码的时候经常看到(sender,e)这两个参数

  private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            Manager.BuyerManager += new Manager.MessageManager(MrZhang.Buyer);          
        }

 

  那么这两个参数究竟有什么含义呢,sender代表的是发送者自己,e包含其内部参数。

  a.而笔者传参的参数就是放在e里面,只是自定义了参数类,继承自EventArgs。

public class EventCollection : EventArgs
    {
        public readonly string work;

        public EventCollection() { }

        public EventCollection(string data)
        {
            this.work = data;
        }
    }

   b.继续刚刚的例子,在委托承担者小张的类里添加含参数工作:

 public static void Work(object sender, EventCollection e)
        {
            MessageBox.Show("小刘" + e.work + "已完成");
        }

  c.在Manager内,添加委托及事件处理细节:

 public delegate void MessageManager2(object sender, EventCollection e);

        public event MessageManager2 WorkManager;

        public void WorkIssue(string work) {
            Onwork(new EventCollection(work));
        }
        //添加保护,只有在委托事件绑定之后才可以实现事件处理。
        public void Onwork(EventCollection e) {

            if (WorkManager != null) {
                WorkManager(this,e);
            }
        }

  d.绑定委托

  Manager Manager = new Manager();
  Manager.WorkManager += new Manager.MessageManager2(MrZhang.Work);
      Manager.WorkIssue("传递文件");

 

五.示例下载

 

六.上述主要用作整理笔记,中间借鉴了很多,附个大神链接http://www.cnblogs.com/wudiwushen/archive/2010/04/20/1698795.html

以上是关于委托与事件——C#版本的主要内容,如果未能解决你的问题,请参考以下文章

C#委托与事件初探

C#语言特性及发展史

C#委托与事件的简单使用

C# 从1到Core--委托与事件

委托与事件——C#版本

C#编程之委托与事件四