C#类型基础引言本文之初的目的是讲述设计模式中的Prototype(原型)模式,但是如果想较清址地弄明白这个模式,需耍了解对象克隆(ObjectClone),Clone具实也就是对象复制。复制乂分为了浅度复制(ShallowCopy)和深度复制(DeepCopy),浅度复制和深度复制又是以如何复制引用类型成员来划分的。由此又引出了引用类型和值类型,以及相关的对象判等、装箱、拆箱等基础知识。于是我干脆新起一篇,从最基础的类型开始自底向上写起了。我仅仅想将对于这个主题的理解表述出来,一是总结和复习,二是交流经验,或许有地方我理解的有偏差,希望指正。如果询而基础的内容对你来说过于简单,可以跳跃阅读。值类型和引用类型我们先简单回顾一下C#中的类型系统。C#中的类型一共分为两类,一类是值类型(ValueType),—类是引用类型(ReferenceType)o值类0和引用类型是以它们在计算机内存屮是如何被分配的来划分的。值类型包括结构和枚举,引用类型包括类、接口、委托等。述冇一种特殊的值类型,称为简单类型⑸mpleType),比如byte,int等,这些简单类型实际上是FCL类库类型的别名,比如声明一个int类型,实际上是声明一个System.lnt32结构类型。因此,在Int32类型中定义的操作,都可以应用在int类型上,比如“123.Equals⑵”。所冇的值类型都隐式地继承自System.ValueType类型(注意System.ValueType木身是一个类类型),System.ValueType和所有的引用类型都继承HSystem.Object基类。你不能显示地让结构继承一个类,因为C#不支持多重继承,而结构已经隐式继承自ValueTypeoNOTE:堆栈(stack)是一种示进先出的数据结构,在内存屮,变暈会被分配在堆栈上来进行操作。堆(heap)是用于为类型实例(对象)分配空间的内存区域,在堆上创建一个对象,会将对象的地址传给堆栈上的变量(反过來叫变量指向此对象,或者变量引用此对象)。1•值类型当声明一个值类型的变量(Variable)的时候,变量木身包含了值类型的全部字段,该变量会被分配在线程堆栈(ThreadStack)上。假如我们有这样一个值类型,它代表了肓线上的一点:publicstructValPoint{publicintx;publicValPoint(intx){this.x=x;}}当我们在程序中写下这样的一条变量的声明语句时:ValPointvPointl;实际产生的效果是声明了vPointl变量,变量本身包含了值类型的所有字段(即你想要的所有数据)。NOTE:如果观察MSIL代码,会发现此时变量还没有被压到栈上,因为.maxstack(最高栈数)为Oo并且没有看到入栈的指令,这说明只有对变量进行操作,才会进行入栈。因为变虽已经包含了值类型的所冇字段,所以,此时你已经可以对它进行操作了(对变量进行操作,实际上是一系列的入栈、出栈操作)。vPointl.x=10;Console.WriteLine(vPoint.x);//输岀10NOTE:如果vPointl是一个引用类型(比如class),在运行时会抛出NullReferenceException异常。因为vPoint是一个值类型,不存在引用,所以永远也不会抛出NullReferenceExceptiono如果你不对vPoint.x进行赋值,直接写Console.WriteLine(vPoint.x),则会出现编译错误:使用了未赋值的局部变量。产生这个错误是因为.Net的一个约束:所冇的元索使用前都必须初始化。比如这样的语句也会引发这个错误:inti;Console.WriteLine(i);解决这个问题我们可以通过这样一种方式:编译器隐式地会为结构类型创建了无参数构造函数。在这个构造隊I数中会対结构成员进行初始化,所有的值类型成员被赋予0或相当于0的值(针对Char类型),所有的引用类型被赋予null值。(因此,Struct类型不可以自行声明无参数的构造函数)。所以,我们可以通过隐式声明的构造函数去创建一个ValPoint类型变量:ValPointvPointl=newValPoint();Console.WriteLine(vPoint.x);//输出为0我们将上面代码第一句的表达式由分隔拆成两部分来看:•左边ValPointvPointl,在堆栈上创建一个ValPoint类型的变量vPoint,结构的所有成员均未赋值。在进行newValPoint()之前,将vPoint压到栈上。•右边newValPoint(),new操作符不会分配内存,它仅仅调川ValPoint结构的默认构造两数,根据构造函数去初始化vPoint结构的所有字段。注意上面这句,new操作符不会分配内存,仅仅调用ValPoint结构的默认构造函数去初始化vPoint...