c#中引用与地址的关系
网络整理 - 06-27
引用是一个模糊的概念。指针与引用类似,可以通过跟踪其位置找到一些数据。但指针更智能,比如可以进行数学运算等。指针也更强大,引用能做的事,指针都能做,反之则不然。指针的缺点是对初学者来说太难理解了,很可能搬石头砸自己的脚。
指针是通过地址实现的。地址是一个数字,表示对进程的整个虚地址空间的一个偏移量(offset)。正因为地址是数字,所以才能对指针进行数学运算。
有些时候,指针是无法替代的;而大多数时候,又不需要这么复杂的概念。因此,C#中既包含指针,也包含引用。
C#语言规范中对引用的描述是十分模糊的:引用类型的变量存储了对某个对象的引用。同样,对指针的描述也是很模糊的:指针变量存储了对象的地址。不过,规范中从来没有说过引用就是地址。因此C#的引用是一个十分模糊的概念。你只能对一个引用进行解引用(dereference),或比较两个引用是否相等,除此之外不能进行任何操作。
实际上,在后台,对于托管对象的引用,CLR将其实现为GC所拥有的对象的地址。但这是实现细节。C#引用应该实现为只对GC有意义的不透明的句柄,只是这个句柄恰巧为运行时地址。这是实现细节,你既不应该知道,也不应该依赖于此。
所以,你不能说“引用即地址”这样的话。它并不是必须为地址,实现细节完全有可能改变。而且对初学者来说,你还要解释什么是地址,什么是偏移量。对了解指针的人来说,还会带来困扰:既然引用和指针都是地址,那么应该可以将引用转换为unsafe的指针。但这是不正确的。
综上所述,如果你不是要向别人解释C#的内存模型,请不要使用“引用即地址”这种论调。我们应该说:引用是一个小的数据块,它包含一些信息,CLR可以根据这些信息来找到引用所指向的对象。这很模糊,但却正确,并且没有多余的暗示。