C# 类型基础 值类型和引用类型

时间:2021-10-27 06:19:52

本文之初的目的是讲述设计模式中的 Prototype(原型)模式,但是如果想较清楚地弄明白这个模式,需要了解对象克隆(Object Clone)Clone其实也就是对象复制。复制又分为了浅度复制(Shallow Copy)和深度复制(Deep Copy),浅度复制深度复制又是以如何复制引用类型成员来划分的。由此又引出了引用类型和值类型,以及相关的对象判等、装箱、拆箱等基础知识。索性从最基础的类型开始自底向上写起。

值类型引用类型

先简单回顾一下C#中的类型系统。C# 中的类型一共分为两类,一类是值类型(Value Type),一类是引用类型(Reference Type)。值类型引用类型是以它们在计算机内存中是如何被分配的来划分的。值类型包括结构和枚举,引用类型包括类、接口、委托等。还有一种特殊的值类型,称为简单类型(Simple Type),比如 byteint等,这些简单类型实际上是FCL类库类型的别名,比如声明一个int类型,实际上是声明一个System.Int32结构类型。因此,在Int32类型中定义的操作,都可以应用在int类型上,比如 "123.Equals(2)"

所有的值类型都隐式地继承自 System.ValueType类型(注意System.ValueType本身是一个类类型)System.ValueType和所有的引用类型都继承自 System.Object基类。你不能显示地让结构继承一个类,因为C#不支持多重继承,而结构已经隐式继承自ValueType

NOTE:堆栈(stack)是一种先进后出的数据结构,在内存中,变量会被分配在堆栈上来进行操作。堆(heap)是用于为类型实例(对象)分配空间的内存区域,在堆上创建一个对象,会将对象的地址传给堆栈上的变量(反过来叫变量指向此对象,或者变量引用此对象)

1.值类型

当声明一个值类型的变量(Variable)的时候,变量本身包含了值类型的全部字段,该变量会被分配在线程堆栈(Thread Stack)上。

假如我们有这样一个值类型,它代表了直线上的一点:

public struct ValPoint { public int X; public ValPoint(int x) { X = x; } }

当我们在程序中写下这样的一条变量的声明语句时:

ValPoint vPoint1;

实际产生的效果是声明了vPoint1变量,变量本身包含了值类型的所有字段(即你想要的所有数据)

编译下面全部代码,用"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\ildasm.exe"(最新)打开编译后的exe。

class Program { private static void Main() { ValPoint vPoint1; } public struct ValPoint { public int X; public ValPoint(int x) { X = x; } } }

NOTE:观察MSIL代码,会发现此时变量还没有被压到栈上,因为.maxstack(最高栈数) 0。并且没有看到入栈的指令,这说明只有对变量进行操作,才会进行入栈。