zoukankan      html  css  js  c++  java
  • [读书笔记]C#学习笔记二: 委托和事件的用法及不同.


    前言: 

    C#委托是什么                                                                                                                                                                                              

    c#中的委托可以理解为函数的一个包装, 它使得C#中的函数可以作为参数来被传递, 这在作用上相当于C++中的函数指针. C++用函数指针获取函数的入口地址, 然后通过这个指针来实现对函数的操作.

    委托的定义和方法的定义类似, 只是在定义的前面多了一个delegate关键字.

    正文:


    委托可以被视为一个更高级的指针,它不仅仅能把地址传指向另一个函数,而且还能传递参数,返回值等多个信息。
    系统还为委托对象自动生成了同步,异步的调用方式,开发人员使用BeginInvoke,EndInvoke方法就可以抛开Thread而直接使用多线程调用。

    一, 委托
    用IL 分析可看出Delegate继承自System.MulticastDelegate类,并自动生成BeginInvoke,EndInvoke,Invoke三种常见的方法。

    Invoke方法是用于同步调用委托对象的对应方法,而BeginInvoke,EndInvoke是用于以异步方式调用对应方法的。

    1.1 简单的委托
    当建立委托对象时,委托的参数类型必须与委托方法相对应。只要向建立委托对象的构造函数中输入方法名称example.Method,委托就会直

    接绑定此方法。
    使用myDelegate.Invoke(string message),就能显式调用委托方法。
    但在实际的操作中,我们无须用到 Invoke 方法,而只要直接使用myDelegate(string message),就能调用委托方法。

     1 class Program
     2 {
     3     void MyDelegate(string message);
     4 
     5     public class Example
     6     {
     7         public void Method(string message)
     8         {
     9             MessageBox.Show(message);
    10         }
    11     }
    12 
    13     static void Main(string[] args)
    14     {
    15         Example example=new Example();
    16         MyDelegate myDelegate=new MyDelegate(example.Method);
    17         myDelegate("Hello World");
    18         Console.ReadKey();
    19     }
    20 }

    1.2 带返回值的委托

    当建立委托对象时,委托的返回值必须与委托方法相对应。使用下面的例子,方法将返回 “Hello Leslie” 。

     1 class Program
     2 {
     3     delegate string MyDelegate(string message);
     4 
     5     public class Example
     6     {
     7         public string Method(string name)
     8         {
     9             return "Hello " + name;
    10         }
    11     }
    12 
    13     static void Main(string[] args)
    14     {
    15         Example example=new Example();
    16         //绑定委托方法
    17         MyDelegate myDelegate=new MyDelegate(example.Method);
    18         //调用委托,获取返回值
    19         string message = myDelegate("Leslie");
    20         Console.WriteLine(message);
    21         Console.ReadKey();
    22     }
    23 }

    1.3 多路广播委托
    在上面提过,委托类继承于MulticastDelegate,这使委托对象支持多路广播,即委托对象可以绑定多个方法。
    当输入参数后,每个方法会按顺序进行迭代处理,并返回最后一个方法的计算结果。
    下面的例子中,Price 类中有两个计算方法,Ordinary 按普通的9.5折计算,Favourable 按优惠价 8.5 折计算。
    委托同时绑定了这两个方法,在输入参数100以后,Ordinary、Favourable这两个方法将按顺序迭代执行下去,最后返回 Favourable 方法的

    计算结果 85。

     1 delegate double MyDelegate(double message);
     2 public class Price
     3 {
     4     public double Ordinary(double price)
     5     {
     6         double price1 = 0.95 * price;
     7         Console.WriteLine("Ordinary Price : "+price1);
     8         return price1;
     9     }
    10 
    11     public double Favourable(double price)
    12     {
    13         double price1 = 0.85 * price;
    14         Console.WriteLine("Favourable Price : " + price1);
    15         return price1;
    16     }
    17 
    18     static void Main(string[] args)
    19     {
    20         Price price = new Price();
    21         //绑定Ordinary方法
    22         MyDelegate myDelegate = new MyDelegate(price.Ordinary);
    23         //绑定Favourable方法
    24         myDelegate += new MyDelegate(price.Favourable);
    25         //调用委托
    26         Console.WriteLine("Current Price : " + myDelegate(100));
    27         Console.ReadKey();
    28     }
    29 }

    1.4 Observer模式中的事件与委托 

     1 class Program
     2 {
     3     public delegate void ObserverDelegate();
     4     
     5     static void Main(string[] args)
     6     {
     7         // 具体主题角色通常用具体自来来实现
     8         ConcreteSubject subject = new ConcreteSubject();
     9 
    10         //传入的只是观察者的通过方法。
    11         subject.Attach(new ConcreteObserver(subject, "Observer A").Update);
    12         subject.Attach(new ConcreteObserver(subject, "Observer B").Update);
    13         subject.Attach(new ConcreteObserver(subject, "Observer C").Update);
    14 
    15         subject.SubjectState = "Ready";
    16         subject.Notify();
    17 
    18         Console.Read();
    19     }
    20 
    21 
    22     //抽象主体类
    23     public abstract class Subject
    24     {
    25         public ObserverDelegate observerDelegate;
    26 
    27         //增加观察者
    28         public void Attach(ObserverDelegate observer)
    29         {
    30             observerDelegate += observer;
    31         }
    32 
    33         //移除观察者
    34         public void Remove(ObserverDelegate observer)
    35         {
    36             observerDelegate -= observer;
    37         }
    38 
    39         //像观察者发通知
    40         public void Notify()
    41         { 
    42             if (observerDelegate != null)
    43             {
    44                 observerDelegate();
    45             }
    46         }
    47     }
    48 
    49     //具体主题类
    50     public class ConcreteSubject : Subject
    51     {
    52         public string SubjectState { get; set; }
    53     }
    54 
    55     //具体观察者
    56     public class ConcreteObserver
    57     {
    58         private string observerState;
    59         private string name;
    60         private ConcreteSubject subject;
    61 
    62         public ConcreteObserver(ConcreteSubject subject, string name)
    63         {
    64             this.subject = subject;
    65             this.name = name;
    66         }
    67 
    68         //实现抽象观察者中的更新操作
    69         public void Update()
    70         {
    71             observerState = subject.SubjectState;
    72             Console.WriteLine("The observer's state of {0} is {1}", name, observerState);
    73         }
    74     }
    75 }

    二,事件 event


    (1) 事件时委托的封装,可以理解为一种特殊的委托。
    (2) 事件里面其实就两个方法(即add_event() 和 remove_event())和一个私有的委托变量,这两个方法里面分别是对这个私有的委托变量进

    行的合并和移除,当调用事件的+=时其实是调用的事件里的add_event()方法,同样-=调用的是remove_event()方法
    (3) 事件只能够从对象外部增加新的响应方法和删除已知的响应方法,而不能主动去触发事件和获取其他注册的响应方法等信息。如果使用

    公有的delegate则不能做这些限制,也就是说事件对委托做了限制,使委托使用起来更加方便。
    也有人说事件是对委托的阉割,大概也是这个意思。

    这里事件没有做过多的阐述, 看到一个关于事件讲解的比较不错的博文, 推荐大家看下吧: http://www.cnblogs.com/landeanfen/p/4721525.html

    PS: 本博客只是为了记录自己学习中的收获, 俗话说 好记性不如烂笔头. 望自己能够坚持下去. 

  • 相关阅读:
    驴的故事
    leetcode125. Valid Palindrome
    C#处理Excel的帮助类
    用SVN进行团队开发协作生命周期详解
    .net反编译原理
    科学使用Log4View2查看日志
    NLog日志框架使用探究-2
    NLog日志框架使用探究-1
    从零开始制作 NuGet 源代码包(全面支持 .NET Core / .NET Framework / WPF 项目)
    十分钟学会 Markdown 基本语法
  • 原文地址:https://www.cnblogs.com/wang-meng/p/5122751.html
Copyright © 2011-2022 走看看