CLR
最后更新于:2022-04-02 00:11:34
# CLR
相信大家在面试的时候会经常问到事件和委托的区别,为什么.net中需要事件和委托这样类似的问题吧,对于一些初学者来说可平时用的过程中也不知道为什么, 只知道这样用,而对于其中的实现机制不是很清楚, 所以面试的时候总是感觉回答的不是很有底气的, 对于委托和事件园子里面也有很多人写过这样的文章,比如张子阳博客中[C# 中的委托和事件](http://www.tracefact.net/CSharp-Programming/Delegates-and-Events-in-CSharp.aspx "C# 中的委托和事件"), 这篇文章由浅入深讲解了.net中的事件和委托。所以比较建议初学者看看的,而且很容易懂.(本人第一次写,如果什么地方说错了的地方请大家海涵和及时纠正我)
在张子阳的文章我相信已经把事件和委托讲的很清楚了,下面我说说我感觉需要注意的地方。
## 为什么会有委托
在C++中用函数指针来实现回调函数(回调函数是一种非常有用的编程机制),然而函数指针不是类型安全的, 所以.net Framework提供了称为**委托**的类型安全的机制来实现函数的回调。
## 编译器如何解析委托
当我们像下面一样在代码中定义一个委托时,
Public delegate void Comparator(int value);
但是编译器遇到这行代码会定义一个类:
View Code
```
1 Public class Comparator:System.MulticastDelegate
2 {
3 public Comparator(Object object, IntPtr method);
4
5 public virtual Void Invoke(Int32 value);
6
7 public virtual IAsyncResult BeginInvoke(Int32 vlaue, AsyncCallback callback, Object object );
8
9 public virtual void EndInvoke(IAsyncResult result);
10
11 }
```
从上面代码可以知道 **委托** 也是一个类,其中有一个构造器,Invoke方法,BeginInvoke方法 和EndInvoke方法。构造器有两个参数,对象引用传给构造器的Object参数,方法的引用传给method 参数,对于静态方法,会为Object 参数传递null.
## **事件**
先看一个事件的定义:
编译器在编译事件的时候会把它转换为三个构造:
```
private Comparator onComparator = null;
public void add_onComparator(Comparator value)
{
// 以一种线程安全的方式对事件添加一个委托
}
public void remove_onComparator(Comparator value)
{
// 以一种线程安全的方式对事件移出一个委托
}
```
从上面代码可以看出第一部分是申明一个私有的委托字段, 后面两部分是对这个委托字段的add访问器和remove 访问器,我们知道属性中有get 和set 访问器,其实事件就是委托字段的访问器,只是访问器方法用add 和remove,而属性用get和set.
## **总结:**
到这里我要讲的差不多说完了, 这是我第一次写文章,尽管上面的内容理解的不是很深入,但是我只是想通过这样的方式来巩固自己看到的知识,因为我觉得这样可以记录下我不同时段对知识的理解以及写的时候自己也在不断思考,这样会有利于对知识的理解。
最后我为初学者推荐关于深入理解.net Framework几本书, 因为我感觉很多初学者不知道买什么书来学习。
1. CLR via C# (第三版) 作者:Jeffrey Richter (周靖译) 清华大学出版社
2. 深入理解C#(第2版)作者:Jon Skeet 周靖(译)人民邮电出版社
现在关于C# 方面的书籍很多,所以对于一些初学者来说不知道怎么选择, 我推荐上面两本书,如果认真的看完的话, 我相信你肯定对.net 会有一定的理解, 然后通过项目实践的方式对书中内容进行巩固。个人觉得要深入理解程序底层的东西, 有必要阅读一些关于操作系统和编译器相关的书籍,本人一向提倡“知其然知其所以然”的学习方式。
在此推荐一本操作系统相关的书籍: 深入理解计算机系统 (美)布莱恩特,奥哈拉伦 著 龚奕利,雷迎春 译 机械工业出版社。
希望这篇文章对大家会有帮助。
作者:Learning hard
出处:[http://www.cnblogs.com/zhili/](http://www.cnblogs.com/zhili/)
';