跟小静学CLR via C#(12)-委托Delegate
2011-08-24 17:51
489 查看
本来按照进度应该学习事件了,可总觉得应该委托在前,事件在后,才好理解。
委托是一个类,它提供了回调函数机制,而且是类型安全的。使用委托可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,提高了程序的可扩展性。
几点说明:
使用关键字delegate声明委托。委托是类型安全的,定义时其返回值类型、参数个数及参数类型要和想要调用的方法兼容。
在这个例子中,通过Introduce方法获取对delegateIntroduce委托对象的引用。委托对象相当于方法的包装器,使方法能通过包装器进行间接回调。
委托即允许调用静态方法(如①②),还允许调用实例方法(③)。
将一个方法绑定到委托时,允许引用类型的协变性和逆变性。(ps:陌生的词汇…)
协变性:方法能返回委托类型的派生类型;
逆变性:方法获取的参数可以是委托类型参数的基类。
注意:这两点只限于引用类型,不能用于值类型或者void。
委托实际上会编译成一个类,包含四个方法:.ctor, Invoke, BeginInvoke, EndInvoke。
所有的委托都会自动继承类System.MulticastDelegate。 MulticastDelegate又继承自Delegate。
MulticastDelegate类提供了三个公共字段:
4. Delegate类提供了两个只读属性:
Target :返回字段_target的值
Method :将字段_methodPtr的值转换为MethodInfo并返回。
例如:
接着上面的例子,我们修改Main方法的调用:
构造委托链时,用到了两个静态方法:
Delegate.Combine(d1,d2) :将委托添加到委托链中。其间_invocationList字段会初始化为一个委托对象数组。上面例子构造完成后该_invocationList[0]被初始化为di1所引用的委托,以此类推。在执行时,发现_invocatonList字段不为空,则会遍历数组元素,顺序调用每个委托包装的方法。
Delegate.Remove (d1,d2) :从d1的委托数组中字段中查找_target和_methodPtr字段与d2匹配的委托,找到后移除。即使匹配记录有多个,每次也只移除一个。
另外,MulticastDelegate类还提供了GetInvocationList()方法,来查看委托链中的委托数组。例如我们将调用委托的Introduce方法略作修改:
+=、-=
C#为委托的+=和-=操作符进行了重载,来简化语法。
执行结果相同。查看IL代码就会发现他们实际调用的是Combine和Remove方法。
THE END.
下次再碰上笔试或者面试的就不用紧张兮兮的了,可以洋洋洒洒的说一通了。
你也许喜欢:跟小静读CLR via C#(00)-开篇及目录
委托是一个类,它提供了回调函数机制,而且是类型安全的。使用委托可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,提高了程序的可扩展性。
使用委托
老规矩,先上个例子:几点说明:
使用关键字delegate声明委托。委托是类型安全的,定义时其返回值类型、参数个数及参数类型要和想要调用的方法兼容。
在这个例子中,通过Introduce方法获取对delegateIntroduce委托对象的引用。委托对象相当于方法的包装器,使方法能通过包装器进行间接回调。
委托即允许调用静态方法(如①②),还允许调用实例方法(③)。
将一个方法绑定到委托时,允许引用类型的协变性和逆变性。(ps:陌生的词汇…)
协变性:方法能返回委托类型的派生类型;
逆变性:方法获取的参数可以是委托类型参数的基类。
注意:这两点只限于引用类型,不能用于值类型或者void。
编译结果
委托实际上会编译成一个类,包含四个方法:.ctor, Invoke, BeginInvoke, EndInvoke。
所有的委托都会自动继承类System.MulticastDelegate。 MulticastDelegate又继承自Delegate。
MulticastDelegate类提供了三个公共字段:
名称 | 类型 | 说明 |
_target | System.Object | 当委托调用静态方法时,该字段为null。当委托调用实例方法时,表示回调方法要操作的对象。 |
_methodPtr | System.InPtr | 标识要回调的方法 |
_invocationList | System.Object | 通常为Null,在委托链时可以引用一个委托数组 |
4. Delegate类提供了两个只读属性:
Target :返回字段_target的值
Method :将字段_methodPtr的值转换为MethodInfo并返回。
例如:
委托链
委托链是由委托对象构成的一个集合。这样就可以将多个方法绑定到同一个委托,调用这个委托的时候会依次调用其所绑定的方法。接着上面的例子,我们修改Main方法的调用:
构造委托链时,用到了两个静态方法:
Delegate.Combine(d1,d2) :将委托添加到委托链中。其间_invocationList字段会初始化为一个委托对象数组。上面例子构造完成后该_invocationList[0]被初始化为di1所引用的委托,以此类推。在执行时,发现_invocatonList字段不为空,则会遍历数组元素,顺序调用每个委托包装的方法。
Delegate.Remove (d1,d2) :从d1的委托数组中字段中查找_target和_methodPtr字段与d2匹配的委托,找到后移除。即使匹配记录有多个,每次也只移除一个。
另外,MulticastDelegate类还提供了GetInvocationList()方法,来查看委托链中的委托数组。例如我们将调用委托的Introduce方法略作修改:
+=、-=
C#为委托的+=和-=操作符进行了重载,来简化语法。
执行结果相同。查看IL代码就会发现他们实际调用的是Combine和Remove方法。
THE END.
下次再碰上笔试或者面试的就不用紧张兮兮的了,可以洋洋洒洒的说一通了。
你也许喜欢:跟小静读CLR via C#(00)-开篇及目录
相关文章推荐
- CLR via C#(12)-委托Delegate
- 跟小静读CLR via C#(05)- 访问限定、数据成员
- 跟小静读CLR via C#(11)-无参属性、索引器
- 委托的杂七杂八---《clr via c#》笔记
- [CLR via C#]12. 泛型
- 跟小静读CLR via C#(15)--String,熟悉而又陌生
- CLR via C# 读书笔记 委托
- 《CLR Via C# 第3版》笔记之(二十四) - 委托
- 跟小静读CLR via C#(08)-操作符
- CLR via C# 3 读书笔记(12):第2章 生成、打包、部署和管理应用程序与类型 — 2.4 将模块组合为程序集(上)
- 跟小静读CLR via C#(14)-可空值类型,关于?和??的故事
- 【转】跟小静读CLR via C#(11)-无参属性、索引器
- 跟小静读CLR via C#(13)-浅谈事件
- 跟小静读CLR via C#(01)-.NET平台下代码是怎么跑起来的
- [CLR via C#]17. 委托
- 跟小静读CLR via C#(16)--泛型
- 读书笔记—CLR via C#委托和attribute
- 跟小静读CLR via C#(18)——Enum
- CLR Via C# 3rd 阅读摘要 -- Chapter 12 - Generics
- 跟小静读CLR via C#(09)-扩展方法