CSharp 里有值类型和引用类型的说法,不知各位看官清楚这两个坏人不,我也是今天才知道他们的使坏之处.
首先,值类型字面上的意思,便是值;引用类型,便是引用.举个简单的例子我与"我",这两个是完全不同的意思,我→单单表示说这字时,是本人在说话;"我"→表示别人在说话.就是这个理.如果要在程序上体现出来的话,则是这样:
1 int me = 0; //这是一个值类型
2 object oMe = me;//这是一个引用类型
也许到这儿,你会觉得没有多大的区别,但实际上,me是存在物理地址上;oMe也是存在物理地址上,但oMe存的东西跟me是不一样的,me所存的就是0的机器码,oMe存的是me的地址.我想,这样子你应该就清楚了.也就是说,oMe存的是一个地址.
如果单单是上面这么简单也就罢了,但是现在,我做如下操作,血案就产生了.
3 object oMe = 0;
4 int me = (int)oMe;
这两句话看似很简单,但它们做的坏事可真不少.首先oMe是一个引用类型,它能够产生,就必须分配两块物理内存,一个存0,一个存0所在的物理地址.
当执行第二句话的时候,这里就更复杂了,先找到oMe所存的值,然后进行类型转换,分配给me物理内存,存下转换后的值.
这就是这两句话所做的事.但实际却又不是这样的.
2执行的时候,其实做了一个强制类型转换(把int转换成object),这个过程叫装箱.
4执行的时候,也做了一个强制类型转换(把objct转换成int),这个过程叫拆箱.
这就是引发的血案,CSharp传说中的装箱拆箱.同时,也引发了托管这个叫人伤心的东西,然后扩散到.NetFrameWrok与CTS的区别.
我们再深入一下:
值类型→放在堆栈里
引用类型→放在托管堆里
也就是说,堆栈→托管堆的过程就是装箱;托管堆→堆栈的过程就是拆箱.
上面我们提到了.NetFrameWrok与CTS的区别,我记得一个同事问过我这样子的一个问题:"你知道int与Int32区别么?" 说实话,那个时候,我还真不知道.只知道在CSharp中,这两个都可以用,当时我的回答是这样的:"Int32是一个类."这个回答只答对了一半,其实最根本的是这样子的:
int 是.NetFrameWrok提供的,Int32是通用类型系统CTS提供的.这就是它们最根本的区别.
int _net = null;//错误,如果真想给null,那么必须这样使用 int? _net = null;
Int32 _cts = null;//错误,如果真想给null,那么必须这样使用 Int32? _net = null;
那么,加上?为什么可以赋值null呢,DBNull.Value与null的区别是什么呢?
不知我这样子说明,大家清楚了没有.