C#基础系列之值类型和引用类型的深入理解
值类型和引用类型
C#中的变量可以分为值类型和引用类型两种。所谓值类型,就是它们在内存中直接存储它们的值,而引用类型则存储对象在内存中的地址。常见的值类型包括整型、浮点型、布尔型和枚举类型,而常见的引用类型包括类、接口、数组和委托等。
值类型使用堆栈空间存储,可以直接访问,速度较快,但是数据量较小,一般在32位系统中为4字节,在64位系统中为8字节。而引用类型的大小是由它们指向的对象所决定的,通常要进行堆内存的分配和释放,速度较慢。
值类型的特点
- 存储在堆栈中;
- 直接包含变量的值,速度快;
- 分配和销毁速度快;
- 值类型不能为 null;
- 值类型实例之间的比较,是比较它们的值是否相等;
下面以整型变量为例展示值类型:
int x = 10; // x 是值类型
int y = x;
y = 20; // x 不会改变
同样是整型,x和y是两个不同的变量,它们在内存中分别存储它们的值,x=10,y=20。将y赋值给x之后,x和y的值都是10。当我们将y的值修改为20时,x的值不会随之改变。
引用类型的特点
- 存储在堆中;
- 存储的是一个指向对象的地址;
- 分配和销毁需要额外的处理;
- 引用类型可以为 null;
- 引用类型实例之间的比较,是比较它们的引用是否相等;
下面以类为例展示引用类型:
class Person {
public string Name { get; set; }
}
Person p1 = new Person() { Name = "Jay" }; // p1 是引用类型
Person p2 = p1; // p1 和 p2 引用同一个对象
p2.Name = "Bob";
Console.WriteLine(p1.Name); // 输出 "Bob"
在这个例子中,我们使用了一个Person类,它存储了一个人的姓名。首先,我们创建了一个名为p1的Person对象,并设置了它的Name属性为"Jay"。然后,我们将p1赋值给了p2,这样p1和p2都指向同一个Person对象。当我们修改p2的Name属性时,p1的Name属性也会发生改变,这是因为它们引用同一个对象。
总结
值类型和引用类型有各自的特点。在开发过程中,我们需要根据实际情况使用不同的类型。通常情况下,如果我们需要存储一个简单的数值类型或者枚举类型等,那么我们可以使用值类型,如果我们需要使用一个较为复杂的对象,那么我们可以使用引用类型。
示例1:值类型
enum Gender { Male, Female }
struct Person {
public string Name { get; set; }
public Gender Gender { get; set; }
}
Person p1 = new Person { Name = "Tom", Gender = Gender.Male };
Person p2 = p1;
p2.Name = "Jerry";
Console.WriteLine(p1.Name); // 输出 "Tom"
在这个示例中,我们定义了一个结构体Person,它包含一个Name属性和一个Gender属性。我们创建了一个Person对象p1,并设置它的Name为"Tom",然后将其赋值给p2。接着,我们修改了p2的Name属性为"Jerry",但p1的Name属性却没有发生改变,这是因为Person是一个结构体,它是一个值类型。
示例2:引用类型
class Cat {
public string Name { get; set; }
public void Speak() {
Console.WriteLine($"{Name}说:喵~");
}
}
Cat c1 = new Cat { Name = "Tom" };
Cat c2 = c1;
c2.Name = "Jerry";
c1.Speak(); // 输出 "Jerry说:喵~"
在这个示例中,我们定义了一个Cat类,它包含一个Name属性和一个Speak方法。首先,我们创建了一个Cat对象c1,并设置它的Name为"Tom",然后将其赋值给c2。接着,我们修改了c2的Name属性为"Jerry",并调用c1的Speak方法,发现输出的是"Jerry说:喵~",这是因为Cat是一个类,它是一个引用类型。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:c#基础系列之值类型和引用类型的深入理解 - Python技术站