[读书笔记]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: 本博客只是为了记录自己学习中的收获, 俗话说 好记性不如烂笔头. 望自己能够坚持下去.

时间: 2024-10-11 01:49:17

[读书笔记]C#学习笔记二: 委托和事件的用法及不同.的相关文章

contiki-main.c 中的process系列函数学习笔记 <contiki学习笔记之六>

说明:本文依然依赖于 contiki/platform/native/contiki-main.c 文件. ------------------------------------------------------------------------------------------------------------------------------------- 根据上一个笔记里面添加的printf()语句的打印信息提示,hello world 打印是在执行了 1 autostart_

[读书笔记]C#学习笔记一: .Net Framwork

前言: 一次偶然的机会  在园子里看到@Learning hard 出版的一本书: <<C#学习笔记>>, 然后买来 一直到现在读完, 感觉很不错, 适合入门, 书中内容是从C#1.0 到5.0. 很全面也很细致. 下面就来分享一下这本书中自己感觉需要记录的一些东西. 这里先贴上@Learning hard本人在博客园的主页: http://www.cnblogs.com/zhili/     以及本书中的一些知识点: http://www.cnblogs.com/zhili/ca

c#学习系列之委托与事件

1. 引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就觉得心里别(biè)得慌,混身不自在.本文中,我将通过两个范例由浅入深地讲述什么是委托.为什么要使用委托.事件的由来..Net Framework中的委托和事件.委托和事件对Observer设计模式的意义,对它们的中间代码也做了讨论. 2. 将方法作为方法的参数 我们先

[读书笔记]C#学习笔记八:StringBuilder与String详解及参数传递问题剖析

前言 上次在公司开会时有同事分享windebug的知识, 拿的是string字符串Concat拼接 然后用while(true){}死循环的Demo来讲解.其中有提及string操作大量字符串效率低下的问题, 刚好自己之前也看过类似的问题, 于是便拿出来记录一下.本文内容: 参数传递问题剖析, string与stringbuilder详解 1,参数传递问题剖析 对于C#中的参数传递,根据参数的类型可以分为四类: 值类型参数的按值传递 引用类型参数的按值传递 值类型参数的按引用传递 引用类型参数的

[读书笔记]C#学习笔记六: C#3.0Lambda表达式及Linq解析

前言 最早使用到Lambda表达式是因为一个需求:如果一个数组是:int[] s = new int[]{1,3,5,9,14,16,22};例如只想要这个数组中小于15的元素然后重新组装成一个数组或者直接让s返回一个新数组该怎么截取? 最开始的想法就是将这个s遍历一遍然后判断下再来重新组装成新的数组.好麻烦是不是? 于是便百度到了一个叫做Lambda的东西, 所以用了之后效果如下: 1 class Program 2 { 3 static void Main(string[] args) 4

《Inside C#》笔记(十二) 委托与事件

C#的委托与C++的函数指针类似,但委托是类型安全的,意味着指针始终会指向有效的函数.委托的使用主要有两种:回调和事件. 一 将委托作为回调函数 在需要给一个函数传递一个函数指针,随后通过函数指针调用函数时,就可以使用回调函数的方式.回调函数经常用于异步编程,如果被调用的方法执行起来比较费时,就可以把这个方法放在单独在线程执行,同时将函数指针交给回调函数,线程结束时再调用回调函数.这样调用者就不必因等待执行起来费时的方法而被阻塞了. a) 举例,有一个数据库管理类DBManager,这个类追踪所

C#学习笔记(四):委托和事件

刚开始学习C#的时候就写过了,直接给地址了: 委托.匿名函数.Lambda表达式和事件的学习 委托学习续:Action.Func和Predicate

[读书笔记]C#学习笔记五: C#3.0自动属性,匿名属性及扩展方法

前言 这一章算是看这本书最大的收获了, Lambda表达式让人用着屡试不爽, C#3.0可谓颠覆了我们的代码编写风格. 因为Lambda所需篇幅挺大, 所以先总结C#3.0智能编译器给我们带来的诸多好处, 下一遍会单独介绍Lambda表达式. 这篇主要包括的内容有: 自动属性,隐式类型,对象集合初始化,匿名类型,扩展方法. 下面一起来看下C#3.0 所带来的变化吧. 1,自动实现的属性在C#3.0之前, 定义属性时一般会像下面这样去编写代码: 1 class Person 2 { 3 //定义私

C#笔记(十九)——委托和事件

课堂练习 using System; using System.Collections.Generic; namespace Lesson13_3 { //张三:初版按钮的实现 /*class Button { public string BtnName { get; set;} public Button(string btnName){ BtnName = btnName; } public void Onclick(){ Console.WriteLine (BtnName+ ":被点击了