zoukankan      html  css  js  c++  java
  • c#中的delegate(委托)和event(事件)

    委托: 托付其他人做这件事   ,包括 托付自己  ,即  一个方法 可以  调用 没有关系的其他方法 , 也可以 将委托传递过去 ,回调自己的方法 ,且 可以自定义参数 ,非常方便 互相传值, 适合解耦 关系。

     示例:

           public delegate void ChangeMoney(object s, int n);   // 用 delegate  声明委托

       1、 调用 其他方法

               售卖 页面添加商品,添加 的 商品 在另一个页面也能看见 。

                     售卖页面 类里面 定义委托:

                        //定义一个委托
                            public delegate void GetProductHander(List<MarkingModel> mlist);
                      // 将创建的委托和特定事件关联
                      public static event GetProductHander getproduct;

               //点击添加商品时  调用 委托方法:                

                       if(点击添加商品)

                          {     

                              getproduct.Invoke(_list);         

                       }     

                 另一个页面调用委托:

                              ProductSaleMarketing.getproduct += new ProductSaleMarketing.GetProductHander(GetList);

                               // 将 要调用的 GetList 方法 放到  getproduct  (从类里面点出来)后面。 以及实现 GetList 方法

                             private void GetList(List<MarkingModel> _mlist)
                            {

                            }

          2.  相当于回调方法

                      这个要在类外面定义委托 ,因为 回调  是 在其他页面实例化委托 ,调用 连接的方法。  谁在后边 后边调用谁。

             

    public delegate void ChangeMoney(object s, int n);  // 在页面外边  声明委托   其他页面都可调用

    public partial class TiHuoBill : BaseForm
    {

                              //多窗口共用事件
                                private void sn_EveDelSelectNumber(object cash, int n)
                                    {
                                        ChangePay(cash, n);
                                     }


                           //现金
                              private void btnCash_Click(object sender, EventArgs e)
                          {
                                 var sn = new ShowNumber(7);
                                       sn.CardMoney = _daishou;
                                       sn.EveDelSelectNumber += sn_EveDelSelectNumber;  //  主要就是 这句话  委托在ShowNumber 页面 实例化了, +=   即  那个页面执行后  调用 sn_EveDelSelectNumber
                                       sn.ShowDialog();
                         }

    }

       ShowNumber 页面 :

              public ChangeMoney EveDelSelectNumber;   //  实例化委托

                       // 确定关闭页面的时候 

                       private void btnSure_Click(object sender, EventArgs e)
                         {

                                     EveDelSelectNumber(SelectMoney, SelectType);  // 调用委托 并传值   或者这种方式:   EveDelSelectNumber.Invoke(SelectMoney, SelectType);

                          }

             暂时发现 委托 可以使用这两种方式

            其中  delegate  和 event  效果 是一样的  

         区别  :event与delegate的区别
     首先,通过加入event关键字,在编译的时候编译器会自动针对事件生成一个私有的字段(与此事件相关的委托),以及两个访问器方法,即add访问器方法以及remove访问器方法,用于对事件的注册及注销(对事件使用+=及-=操作时就是调用的这两个方法)。
    我想你们的问题主要是,实际上声明一个委托类型的字段也可以实现这些功能。
    实际上之所以采用event而不直接采用委托,实际上还是为了封装。可以设想一下,如果直接采用公共的委托字段,类型外部就可以对此字段进行直接的操作了,比如将其直接赋值为null。
    而使用event关键字就可以保证对事件的操作仅限于add访问器方法以及remove访问器方法(即只能使用+=及-=)

      

        在Msdn中,有一段话描述Delegate和Event之间的关系,其实很简单:

            声明事件:若要在类内声明事件,首先必须声明该事件的委托类型。

        委托还适用于 观察者模式:

                     

        class Program
        {
            static void Main(string[] args)
            {
                var car = new Car(15);
                new Alerter(car);
                car.Run(120);
            }
        }
    
        class Car
        {
            public delegate void Notify(int value);
            public event Notify notifier;
    
            private int petrol = 0;
            public int Petrol
            {
                get { return petrol; }
                set
                {
                    petrol = value;
                    if (petrol < 10)  //当petrol的值小于10时,出发警报
                    {
                        if (notifier != null)
                        {
                            notifier.Invoke(Petrol);
                        }
                    }
                }
            }
    
            public Car(int petrol)
            {
                Petrol = petrol;
            }
    
            public void Run(int speed)
            {
                int distance = 0;
                while (Petrol > 0)
                {
                    Thread.Sleep(500);
                    Petrol--;
                    distance += speed;
                    Console.WriteLine("Car is running... Distance is " + distance.ToString());
                }
            }
        }
    
        class Alerter
        {
            public Alerter(Car car)
            {
                car.notifier += new Car.Notify(NotEnoughPetrol);
            }
    
            public void NotEnoughPetrol(int value)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("You only have " + value.ToString() + " gallon petrol left!");
                Console.ResetColor();
            }
        }

    看完了上面的代码后,你可能会问:为什么不在public int Petrol中直接调用Alerter.NotEnoughPetrol呢?因为Car模块和Alerter模块本身是两个独立的子系统,如果直接调用,耦合性就会增加,这不是我们愿意看到的。

        其实以上的代码是设计模式中的观察者模式(观察者模式又称Source/Listener模式)的实现,当汽车在运行中汽油量<10时,警报器便会发出警报。在上面代码中,Delegate相当于一个存放回调函数的函数指针,使用Delegate,我们可以非常方便地实现观察者模式。而其实,在需要使用回调函数时,我们都可以考虑使用Delegate。

        不知道你有没有发现在上面的代码中还有一个问题呢?

    public event Notify notifier;

    上面的代码中,我们定义了一个Event,而事实上:

    public Notify notifier;

    这样写,也完全可以满足我们的需求,这就引出了我们的另一个问题,Delegate和Event!  如上 有说明。

                   参考:   谈C#中的Delegate

                                 event与delegate的区别

                                终于会用c#中的delegate(委托)和event(事件)了

  • 相关阅读:
    数据结构_bubble_sort
    数据结构_sfdg(小F打怪)
    数据结构_yjjsj(伊姐姐数字游戏)
    数据结构 queue
    数据结构 Job
    数据结构 happiness
    数据结构_calculator
    js并归排序的思路
    js神秘的电报密码---哈弗曼编码
    js同时获得数组的两个最小值
  • 原文地址:https://www.cnblogs.com/awake-insist/p/7418704.html
Copyright © 2011-2022 走看看