C# - 值类型和引用类型(Value Type and Reference Type)

本文关键字:Type Value and Reference 引用类型 类型 | 更新日期: 2023-09-12 17:38:31

在 C# 中,这些数据类型根据它们在内存中存储其值的方式进行分类。C# 包括以下类别的数据类型:

  1. 值类型
  2. 引用类型
  3. 指针类型

值类型

如果数据类型将数据值保存在自己的内存空间中,则该数据类型是值类型。这意味着这些数据类型的变量直接包含值。

例如,考虑整数变量int i = 100;

系统在分配给变量i的内存空间中存储100。下图说明了如何将 100 存储在内存 (0x239110) 中某个假设位置的"i":

值类型变量的内存分配

以下数据类型均为值类型:

  • bool
  • bool
  • byte
  • char
  • decimal
  • double
  • enum
  • float
  • int
  • long
  • sbyte
  • short
  • struct
  • uint
  • ulong
  • ushort

传递值类型变量

将值类型变量从一个方法传递到另一个方法时,系统会在另一个方法中创建变量的单独副本。如果值在一个方法中发生了更改,则不会影响另一个方法中的变量。

Example: Passing Value Type Variables

static void ChangeValue(int x)
{
    x =  200;
    Console.WriteLine(x);
}
static void Main(string[] args)
{
    int i = 100;
    Console.WriteLine(i);
    
    ChangeValue(i);
    
    Console.WriteLine(i);
}

输出:

100
200
100

在上面的示例中,Main() 方法中的变量i保持不变,即使我们将它传递给 ChangeValue() 方法并更改其值。

引用类型

与值类型

不同,引用类型不直接存储其值。相反,它存储存储值的地址。换句话说,引用类型包含指向保存数据的另一个内存位置的指针。

例如,请考虑以下字符串变量:

string s = "Hello World!!";

下图显示了系统如何为上述字符串变量分配内存。

引用类型变量的内存分配

如上图所示,系统在内存(0x803200)中为变量s选择一个随机位置。 变量s的值是 0x600000 ,这是实际数据值的内存地址。因此,引用类型存储存储实际值的位置的地址,而不是值本身。

以下是引用类型数据类型:

  • String
  • 数组(即使它们的元素是值类型)
  • 委托

传递引用类型变量

将引用类型变量从一个方法传递到另一个方法时,它不会创建新的副本;而是传递变量的地址。因此,如果我们更改方法中变量的值,它也将反映在调用方法中。

Example: Passing Reference Type Variable

static void ChangeReferenceType(Student std2)
{
    std2.StudentName = "Steve";
}
static void Main(string[] args)
{
    Student std1 = new Student();
    std1.StudentName = "Bill";
    
    ChangeReferenceType(std1);
    Console.WriteLine(std1.StudentName);
}

输出:

Steve

在上面的示例中,我们将Student对象std1传递给 ChangeReferenceType() 方法。在这里,它实际上传递了std1的内存地址。 因此,当ChangeReferenceType()方法更改StudentName时,它实际上是在更改std1对象的StudentName,因为std1std2都指向内存中的同一地址。

String 是一种引用类型,但它是不可变的。这意味着一旦我们分配了一个值,它就无法更改。如果我们更改字符串值,则编译器会在内存中创建一个新的字符串对象,并将变量指向新的内存位置。 因此,将字符串值传递给函数将在内存中创建一个新变量,并且函数中值的任何更改都不会反映在原始值中,如下所示。

Example: Passing String

static void ChangeReferenceType(string name)
{
    name = "Steve";
}
static void Main(string[] args)
{
    string name = "Bill";
    
    ChangeReferenceType(name);
    Console.WriteLine(name);
}

输出:

Bill

Null

引用类型变量的默认值在未初始化时nullNull意味着不引用任何对象。

Null 引用类型

值类型变量不能为 null,因为它保存值,而不是内存地址。 C# 2.0 引入了nullable 类型,使用该类型可以将 null 分配给值类型变量或声明值类型变量而不为其赋值。