C#的值类型和引用类型详解

215 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情

C#中有哪些值类型

  • 内置类型中的所有的数字类型,char, bool
  • 结构体类型 struct
  • 枚举类型 enum

C#中有哪些引用类型

  • class
  • 内置数组类型 array
  • 委托类型 delegate
  • 接口类型 interface
  • 内置的string类型

值类型和引用类型的核心区别在于它们的内存使用方式

值类型如何使用内存

  • 值类型的变量或常量,它的值保存的就是变量或常量本身的值。
  • 例如int型的变量,其内部保存的就是32bit的数据。
  • 自定义值类型使用结构体,例如:
public struct Point
{
    public int X;
    public int Y;
}

那么在内存中,Point类型的变量实例中存储的内容就是X和Y:

image.png

  • 值类型对象的实例赋值时会拷贝实例的内容。 例如:
Point p1 = new Point();
p1.X = 2;
Point p2 = p1;
Debug.Log(p1.X); // 2
Debug.Log(p2.X); // 2
p1.X = 3;
Debug.Log(p1.X); // 3
Debug.Log(p2.X); // 2

引用类型如何使用内存

  • 引用类型的变量包含两个部分:对象以及指向对象的引用。
  • 引用类型的变量的值保存的是指向一个对象的引用,而对象中保存的是自身的对象属性值。
  • 上面的Point的例子使用class改写,那么内存中的布局如下:

image.png

  • 赋值给引用类型的变量时,会拷贝引用值,而不是对象实例。这允许多个变量指向同一个对象。
  • 引用类型变量可以赋值为 null,表示不指向任何对象。

值类型一定存储在栈上吗?

并不是,值类型的意思仅仅是变量存值本身。所以当值类型变量单独出现时,它的值就是保存在栈上的。而当值类型变量作为一个引用类型对象的成员时,例如类的值类型成员,此时由于引用类型变量的内容是保存在堆上的,因此其成员的值类型变量的值也是保存在堆上的。