zoukankan      html  css  js  c++  java
  • [C#]委托和事件

    参考链接:

    https://www.cnblogs.com/JimmyZhang/archive/2007/09/23/903360.html

    https://www.cnblogs.com/JimmyZhang/archive/2008/08/22/1274342.html

    1.委托

    a.定义一个委托就是定义一个类(委托会在编译的时候被编译成类)。因为委托是一个类,所以可以在任何可以声明类的地方来声明委托

    b.委托定义了方法的类型,使得可以将方法当作参数来传递

    c.可以将多个方法绑定到同一个委托变量,当调用该变量时,会依次调用所有绑定的方法

     1 using System;
     2 
     3 namespace ConsoleApp1
     4 {
     5     public delegate void GreetingDelegate(string name);
     6 
     7     class Program
     8     {
     9         private static void EnglishGreeting(string name)
    10         {
    11             Console.WriteLine("Morning, " + name);
    12         }
    13 
    14         private static void ChineseGreeting(string name)
    15         {
    16             Console.WriteLine("早上好, " + name);
    17         }
    18 
    19         private static void GreetPeople(string name, GreetingDelegate MakeGreeting)
    20         {
    21             MakeGreeting(name);
    22         }
    23 
    24         static void Main(string[] args)
    25         {
    26             GreetingDelegate delegate1;
    27             delegate1 = EnglishGreeting;       // 先给委托类型的变量赋值
    28             delegate1 += ChineseGreeting;   // 给此委托变量再绑定一个方法
    29 
    30             // 将先后调用 EnglishGreeting 与 ChineseGreeting 方法
    31             GreetPeople("Jimmy Zhang", delegate1);
    32             Console.ReadKey();
    33 
    34             //输出为:
    35             //Morning, Jimmy Zhang
    36             //早上好, Jimmy Zhang
    37         }
    38     }
    39 }

    2.事件

    a.事件是对委托的封装

    如下,对于这样的一个事件:

    public event GreetingDelegate MakeGreet;

    会被编译成:

    private GreetingDelegate MakeGreet; //对事件的声明 实际是 声明一个私有的委托变量
     
    [MethodImpl(MethodImplOptions.Synchronized)]
    public void add_MakeGreet(GreetingDelegate value){
        this.MakeGreet = (GreetingDelegate) Delegate.Combine(this.MakeGreet, value);
    }
    
    [MethodImpl(MethodImplOptions.Synchronized)]
    public void remove_MakeGreet(GreetingDelegate value){
        this.MakeGreet = (GreetingDelegate) Delegate.Remove(this.MakeGreet, value);
    }

    即一个事件,被编译后会产生一个private的委托变量,还有2个方法用于注册和取消注册委托(即+=和-=,这2个方法的访问权限等同于该事件的访问权限,事件为public即2个方法也为public)

    例子:

     1 using System;
     2 
     3 namespace ConsoleApp1
     4 {
     5     public delegate void GreetingDelegate(string name);
     6 
     7     public class GreetingManager
     8     {
     9         public event GreetingDelegate MakeGreet;
    10 
    11         public void GreetPeople(string name)
    12         {
    13             MakeGreet(name);
    14         }
    15     }
    16 
    17     class Program
    18     {
    19         private static void EnglishGreeting(string name)
    20         {
    21             Console.WriteLine("Morning, " + name);
    22         }
    23 
    24         private static void ChineseGreeting(string name)
    25         {
    26             Console.WriteLine("早上好, " + name);
    27         }
    28 
    29         static void Main(string[] args)
    30         {
    31             GreetingManager gm = new GreetingManager();
    32             gm.MakeGreet += EnglishGreeting;
    33             gm.MakeGreet += ChineseGreeting;
    34 
    35             gm.GreetPeople("Jimmy Zhang");
    36             Console.ReadKey();
    37 
    38             //输出为:
    39             //Morning, Jimmy Zhang
    40             //早上好, Jimmy Zhang
    41         }
    42     }
    43 }

    3.其他

    a.委托和事件对应的是观察者模式,一对多的关系

    b.委托和事件的区别在于,事件只能由事件发布者触发(即只能在定义事件所在的类内部触发),而委托则没有这个限制,委托类似于string,是一个变量的类型

    c.委托定义的返回值通常为void,这是因为委托变量可以供多个订阅者注册,如果定义了返回值,那么多个订阅者的方法都会向发布者返回数值,结果就是后面一个返回的方法值将前面的返回值覆盖掉了,因此,实际上只能获得最后一个方法调用的返回值。所以返回订阅者的方法返回值大多数情况下根本没有必要

  • 相关阅读:
    内存溢出异常
    Java堆中的对象
    运行时数据区域
    字符串常量池
    自己编译JDK
    @PathVariable注解详解
    spring容器监听器
    redis和spring整合
    Redis安装、启动、关闭
    HDU3974 Assign the task
  • 原文地址:https://www.cnblogs.com/lyh916/p/12003715.html
Copyright © 2011-2022 走看看