CLR VIA C#教程之基元类型 值类型 引用类型介绍

开发 后端
CLR Via C#教程基元类型 值类型 引用类型介绍,对原文例子表示值类型和引用类型的区别进行代码分析,CLR中类型字段布局的控制。

我很喜欢《CLR Via C#》这本书,但一直都没能深入理解,而且很多内容也忘记了,现在准备重新看一遍,并将看过的部分写出来,因为写的过程也是一个加深理解的过程。本系列算是学习的一个记录吧,也可以方便以后自己查阅,如果对大家还有些帮助的话,我就很高兴了。书我是选择性的看的,所以顺序和书中的顺序可能不一样。

首先了解下什么是基元类型,基元类型是编译器直接支持的数据类型,像我们平时经常用到的int string bool 都是基元类型,基元类型是映射到FCL中的类型,像前面的三种类型对应到FCL中就是Int32 String Boolean,基元类型只是给我们的编程提供了方便,它和FCL中的类型在编译后最终生成的IL完全相同。下面给出基元类型和FCL类型的对应表
我们平时在写程序时通常都是使用基元类型,因为方便,但本书的作者认为应该直接使用FCL中的类型,原因如下:

C#基元类型

FCL类型

CLS相容

说明

sbyte

System.Sbyte

 

 

byte

System.Byte

 

 

short

System.Int16

 

 

ushort

System.UInt16

 

 

int

System.Int32

 

 

uint

System.Uint32

 

 

long

System.Int64

 

 

ulong

System.Uint64

 

 

char

System.Char

 

 

float

System.Single

 

 

double

System.Double

 

 

bool

System.Boolean

 

 

decimal

System.Decimal

 

 

object

System.Object

 

 

string

System.String

 

 

 

在c#中long对应的FCL类型为System.Int64,但是在其他的语言中,如c++ 就将long视为一个Int32。这样习惯于一种编程语言的人在看另一种编程语言写的源码是就会产生错误的理解。在FCL中的许多的方法将类型名作为方法名的一部分,如System.Convert类提供ToBoolean,ToInt32,ToSingle等。这样在使用基元类型做类型转换时就感觉有点怪怪的,如:float val=Convert.ToSingle(“23”);

CLR VIA C#教程之值类型和引用类型的区别
1.所有的值类型都是从System.TypeValue派生,如Struct Enum都是值类型;所有引用类型都是从System.Object派生。
2.值类型分配在线程堆栈上,引用类型分配在托管堆上。
3.值类型表现形式有未装箱形式和已装箱形式,而引用类型总是已装箱形式。
4.所有的值类型都是sealed类型,所以值类型不能作为任何类型的基类型,也不能在值类型中引入虚方法。
5.创建一个引用类型变量时,会被初始化为null,试图使用一个null的引用类型变量时,会抛出NullReferenceException异常,也就是常见的“未将对象引用设置到对象的实例”;值类型在创建时所有成员都初始化为0了,所以不会抛出该异常。

原文例子表示值类型和引用类型的区别

  1. class Program  
  2. {  
  3. static void Main(string[] args)  
  4. {  
  5. SomeRef r1 = new SomeRef();  
  6. SomeVal v1 = new SomeVal();  
  7. r1.x = 5;  
  8. v1.x = 5;  
  9. Console.WriteLine(r1.x);    //5  
  10. Console.WriteLine(v1.x);    //5  
  11. SomeRef r2 = r1;  
  12. SomeVal v2 = v1;  
  13. r1.x = 8;  
  14. v1.x = 9;  
  15. Console.WriteLine(r1.x);    //8  
  16. Console.WriteLine(r2.x);    //9  
  17. Console.WriteLine(v1.x);    //9  
  18. Console.WriteLine(v2.x);    //5  
  19. }  
  20. }  
  21. class SomeRef  
  22. {  
  23. public Int32 x;  
  24. }  
  25. struct SomeVal  
  26. {  
  27. public Int32 x;  


CLR VIA C#教程之CLR中类型字段布局的控制

为了提高性能,clr能按照所选择的任何方式来排列类型的字段。我们可以通过在类会是结构上使用System.Runtime.InteropServices.StructLayoutAttribute属性来改变这种排列的顺序。该属性接受一个LayoutKind的枚举值(Auto,Sequential,Explicit),默认情况下C#编译器会为类选择Atuo,为结构选择Sequential。下面来定义一个类和一个结构

  1. struct SomeVal  
  2. {  
  3. public String name;  
  4. public Int32 id;  
  5.  
  6. }  
  7.  
  8. class SomeRel  
  9. {  
  10. public String name;  
  11. public Int32 id;  
  12. }  

查看IL代码可以看到默认的排列顺序

默认的排列顺序 

现在给类和结构加上属性,首引用加命名空间 using System.Runtime.InteropServices;

  1. [StructLayout(LayoutKind.Auto)]  
  2. struct SomeVal  
  3. {  
  4. public String name;  
  5. public Int32 id;  
  6. }  
  7. [StructLayout(LayoutKind.Sequential)]  
  8. class SomeRel  
  9. {  
  10. public String name;  
  11. public Int32 id;  

再查看IL可以看到顺序已经发生了变化

    顺序变化页面 

 

 C#编译器总是会默认给结构这样的值类型选择Sequential,是因为值类型会经常和非托管代码进行交互,字段必须保持和开发人员定义的一致。我们在编码过程中如果判断所创建的值类型不会与非托管代码进行交互,就可以像上面那样给创建的值类型添加[StructLayout(LayoutKind.Auto)] ,让其进行自动排列,以提高性能。

查看IL代码可以看到默认的排列顺序,以上是CLR VIA C#教程系列之一。

【编辑推荐】

  1. 全面解析CLR是什么一点通
  2. 为你解疑C++ CLR和ISO C++原理区别
  3. 趣谈CLR中的静态构造函数
  4. CLR VB.NET学习经验
  5. 深入解析.Net CLR函数使用举例
责任编辑:田树 来源: 博客
相关推荐

2009-08-19 16:39:44

C#值类型C#引用类型

2009-08-26 14:05:19

C#值类型和引用类型

2009-08-03 17:51:43

C#引用类型

2011-06-08 13:03:52

C#值类型引用类型

2009-10-22 19:11:25

CLR Via C#教

2013-05-23 17:21:16

C#

2009-08-03 14:54:23

值类型C#

2009-08-14 17:09:48

C#引用类型

2009-08-31 14:34:46

C#值类型C#结构类型

2009-08-27 16:39:26

C# String类型

2009-09-11 11:09:36

C#引用类型

2009-09-11 11:17:04

C#引用类型

2009-09-03 16:55:58

C#引用类型

2009-08-06 10:14:15

C#引用类型数组

2009-08-18 17:17:05

C#局部类型

2009-08-27 10:19:22

C#匿名类型

2009-08-14 17:04:50

C#类型系统

2009-10-10 09:53:07

.NET值类型

2009-06-15 17:05:03

C#基元类型

2009-09-18 09:02:45

CLR Via C#
点赞
收藏

51CTO技术栈公众号