现在的位置: 首页 > 综合 > 正文

CLR vir C# 之基类型,值类型,引用类型

2012年11月25日 ⁄ 综合 ⁄ 共 1293字 ⁄ 字号 评论关闭

     基类型

     之前有过这样的疑惑:int 和System.Int32有什么不同?实际上System.Int32是再FCL中的定义,多数编译器对于此等类型都有自己的定义,他们和FCL中的定义自动建立映射关系。如C#中System.Int32就映射为int.

     所以我们可以很方便的用int i=10进行定义,实际上编译为IL后,可以看到其以Int32的映射出现。

     FCL中的类型在C#都有对应的基元类型,但是在CLS中却不一定有,如Sbyte,uint等。

     特别要注意的是:类型转换时,如果大范围向小范围类型转换,需要强制转换,编译器将做截断处理;反之,可以安全的隐式转换。

     Single s2 = 6.8F;
     Console.WriteLine((int)s2); //output:6

      

     Checked/UnChecked

     此关键字,用来对表达式或语句块进行安全性检查。判断运算是否有溢出产生。

     在IL中,每个运算符(+,-,*,/)都对应一对指令,如+对应Add和Add.ovf。调用后者时,将进行溢出检查。

     这样,我们在使用此关键字时,实际上调用了IL中对应的指令而已。

     溢出检查动作将使得应用程序性能受到影响。     

     值类型和引用类型

     1.结构体和枚举类型属于值类型,其余都为引用类型。

     2.引用类型存储在托管堆上,同时需要存储额外的信息,受GC的控制。

     3.值类型存储在线程栈中,不受GC控制,出了作用域,自动释放。

     4.值类型的赋值和传递,需要进行字段的复制和存储,而引用类型只传递指针。

     通常在作为参数传递和作为返回值传递时,如果数据过大,不易用值类型。

     

     装箱和拆箱

     值类型有两种状态:装箱状态和拆箱状态;引用类型只有一种:装箱状态。

     通常当值类型作为参数传递时,而接受参数方接受参数类型为引用类型时,将发生装箱作业。

     装箱时:

     1.在托管堆分配值类型字段需要的内存,同时还要为附加信息分配空间(类型对象指针,同步块索引)。

     2.数值copy至堆中

     3.返回存储指针

     可见,装箱作业是非常消耗性能的。所以我们在写程序过程中,应当尽可能避免装箱情况的出现。net2.0出现的泛型,实际上一方面的原因就在于此。

     如:Console.WrileLine(12+"test")---> Console.WriteLine(12.ToString()+"test");之间的性能可测试。

     拆箱时:
      1.获取已装箱对象的各个字段的地址。
      2.将这些字段包含的值从堆中复制到基于堆栈的值类型实例中。
      引用变量如果为null,拆箱时抛出NullRefernceException异常;拆箱时如果不能正确转型,则抛出InvalidCastException异常。
      装箱之前是什么类型,拆箱时也要转成该类型,转成其基类或子类都不行。

抱歉!评论已关闭.