值类型和引用类型

一、值类型和引用类型

在 C# 中,数据类型可以分为值类型(Value Types)和引用类型(Reference Types),它们有着不同
的特点和行为。以下是值类型和引用类型的区别:

1. 值类型(Value Types):

  • 值类型直接包含数据本身,存储在栈(Stack)上。
  • 值类型包括整数类型(int、long)、浮点数类型(float、double)、字符类型(char)、结构体(struct)、枚举(enum)。
  • 值类型的变量是值的拷贝,修改一个变量的值不会影响到另一个变量。
int a = 10;
int b = a;
b = 20;
// 此时a仍然是10,b变为20

2. 引用类型(Reference Types):

  • 引用类型存储在堆(Heap)中,变量存储的是对象的引用(地址)。
  • 多个变量可以引用同一个对象,对一个变量做修改会影响到其他引用同一对象的变量。
  • 具体的引用类型包括类(class)、接口(interface)、委托(delegate)以及字符串(string)等。
  • 传递引用类型变量时,传递的是引用的副本,所以多个引用指向的是同一个对象。
List<string> list1 = new List<string>();
List<string> list2 = list1;
list1.Add("A");
// list2 也会包含 "A",因为它们引用同一个 List<string> 对象

3. 值类型和引用类型的内存分配:

  • 值类型的内存分配是在栈上分配,操作简单高效,但不能动态分配内存。
  • 引用类型的内存分配是在堆上分配,动态分配和释放内存,需要进行垃圾回收(GarbageCollection)。

4. 结合值类型和引用类型的注意事项:

  • 在传递值类型时,传递的是值的副本,不会影响原始值。
  • 在传递引用类型时,传递的是引用的副本,会影响对象的状态。

在编写 C# 代码时,了解值类型和引用类型的特点和区别,有助于避免一些潜在的问题并更好地理解代码执行过程。

二、结构体

在 C# 中,结构体(Struct)是一种用户自定义的值类型(Value Type),它可以包含多个不同类型的字段(Fields)。结构体是轻量级的数据结构,适合用于简单的数据封装和传递,相对于类(Class)而言,结构体更适合用于存储小型的数据集合。以下是一些关于 C# 结构体的基本知识:

1. 结构体声明:

结构体的声明使用 struct 关键字,通常位于命名空间内或其他类的内部。

public struct Person
{
	public string name;
	public int age;
}

2. 结构体特点:

  • 结构体是值类型,存储在栈上,而类是引用类型,存储在堆上。
  • 结构体没有继承性,不能包含默认构造函数,不能用作基类,也不能成为其他类的基类。
  • 结构体可以包含字段、属性、方法、构造函数等成员。

3. 结构体实例化:

可以使用 new 关键字来实例化结构体,也可以直接声明并赋值。

(结构体的实例化不代表分配内存,仅仅只是执行构造函数)

(结构体中存在默认构造函数,但不能显式的定义,可以构造有参数的构造函数)

Person person1 = new Person();
person1.name = "Alice";
person1.age = 30;
Person person2 = new Person { name = "Bob", age = 25 };

4. 结构体与类的比较:

  • 结构体适合用于小型的数据封装和传递,无需频繁的实例化和销毁。
  • 结构体在参数传递时是按值传递,而类是按引用传递。
  • 使用结构体可以避免引用类型的一些问题,如空引用异常等。

5. 注意事项:

  • 结构体适合用于简单的数据表示,不适合用于包含复杂逻辑和大量数据的场景。
  • 结构体占用的内存较少,但大量的结构体实例化会增加栈内存的使用,需要谨慎使用。

通过合理地使用结构体,你可以更高效地组织和管理数据,尤其是在需要频繁传递和处理小型数据集合
的情况下。

三、枚举

在 C# 中,枚举(Enumeration)是一种用于定义命名常量集合的数据类型。枚举可以帮助代码更具可读
性和可维护性,避免使用魔术数字。以下是关于 C# 中枚举的基本知识:

1. 枚举声明:

枚举使用 enum 关键字声明,定义了一组命名的常量。枚举成员的值从 0 开始递增,可以显式指定初始值。

public enum DaysOfWeek
{
	Monday,// 0
	Tuesday,// 1
	Wednesday, // 2
	// 可以继续列举其他成员
}

2. 枚举使用:

可以通过枚举名称和成员名称来访问枚举常量。

 

DaysOfWeek day = DaysOfWeek.Monday;
Console.WriteLine(day); // 输出: Monday

int dayValue = (int)DaysOfWeek.Tuesday; // 转换为整数

3. 指定枚举成员的值:

 

可以显式指定枚举成员的值,后续成员的值会自动递增。

public enum Status
{
	InProgress = 1,
	Completed = 2,
	Canceled = 3
}

4. 枚举标志(Flags):

使用 [Flags] 特性可以将枚举用作标志位,可以组合多个值。

[Flags]
public enum Permissions
{
	Read = 1,
	Write = 2,
	Delete = 4
}
Permissions userPermission = Permissions.Read | Permissions.Write;
bool hasWritePermission = (userPermission & Permissions.Write) ==Permissions.Write;

5. 枚举转换:

  • 可以使用强制类型转换将枚举转换为整数等类型。
  • 可以使用 Enum.Parse() 方法将字符串转换为枚举值。
int value = (int)DaysOfWeek.Wednesday; // 转换为整数
DaysOfWeek Friday = (DaysOfWeek)Enum.Parse(typeof(DaysOfWeek), "Friday");

6. 注意事项:

  • 枚举默认基础类型为 int ,可以显式指定其他整数类型。
  • 枚举的成员名称必须唯一,但值不需要唯一。
  • 可以将枚举嵌套在类或结构中。

通过合理使用枚举,可以使代码更清晰易懂,并提高代码的可维护性。结合枚举可以使代码中的常量更具有语义性。

“您的支持是我持续分享的动力”

微信收款码
微信
支付宝收款码
支付宝

目录