结构体
大约 3 分钟
在 C# 中,结构体(struct)是一种值类型(value type),用于组织和存储相关数据。结构体可用于存储各种数据类型的相关变量,使用 struct
关键字来创建结构体。
如何使用?
定义一个结构体
结构体内部可以包含字段、方法、属性、索引器、运算符和事件等成员。
例如,定义一个表示三维点的结构体:
struct Point3D
{
public double X;
public double Y;
public double Z;
// 构造函数
public Point3D(double x, double y, double z)
{
X = x;
Y = y;
Z = z;
}
// 方法
public double DistanceToOrigin()
{
return Math.Sqrt(X * X + Y * Y + Z * Z);
}
}
结构体的实例化
结构体的实例化可以使用 new
关键字来调用构造函数:
Point3D point1 = new Point3D(1.0, 2.0, 3.0);
也可以直接赋值,如果不使用 new
关键字,则必须初始化所有字段:
Point3D point2;
point2.X = 4.0;
point2.Y = 5.0;
point2.Z = 6.0;
结构体实例可以使用成员运算符(.
)来访问其成员:
Console.WriteLine(point1.X); // 输出:1
Console.WriteLine(point2.DistanceToOrigin()); // 输出:8.774964387392123
结构体的特点
特点 | 结构体 |
---|---|
成员 | 可以包含字段、方法、属性、索引器、运算符和事件等成员。不能包含抽象方法、虚方法或受保护成员 |
构造函数 | 可以定义构造函数,但不能定义析构函数,也不能定义无参构造函数。无参构造函数(默认)是自动定义的,且不能被改变。 |
继承 | 不能继承其他结构体或类。不能作为基类被继承 |
接口 | 可以实现一个或多个接口 |
实例化 | 可以使用 new 关键字来创建结构体实例。可以不使用 new 关键字直接赋值,但需要先初始化所有字段 |
内存分配 | 结构体变量通常分配在栈上,效率较高。作为引用类型类成员的结构体会分配在堆上 |
可变性 | 默认情况下是可变的,即字段值可以修改。可以定义为只读结构体,使字段值不可变 |
应用场景 | 适用于表示轻量级数据,例如:点、大小、颜色、日期、时间等。常用作值类型参数或返回值。作为内部数据结构,例如集合中的元素 |
结构体 vs 类
- 值类型与引用类型:
- 结构体是值类型(
value type
),这意味着当结构体被赋值给一个新的变量时,会创建该值的一个副本。 - 类是引用类型(
reference type
),这意味着当类的实例被赋值给一个新的变量时,两个变量都引用同一个对象实例。
- 结构体是值类型(
- 内存分配:
- 结构体的实例通常在栈上分配(尽管在闭包或作为类的成员时可以在堆上分配),这使得它们的分配和回收更快。
- 类的实例总是在堆上分配,这可能导致更慢的分配速度和垃圾回收的开销。
- 继承:
- 结构体不能继承其他的结构体或类,但它们可以实现接口。
- 类可以继承其他类,这意味着它们可以形成一个继承层次结构。
- 默认的构造函数:
- 结构体总是有一个默认的无参数构造函数,不能被重写。
- 类可以没有构造函数,也可以定义一个或多个构造函数,包括无参数的构造函数。
- 初始化:
- 在结构体中,所有的字段必须在对象被使用之前初始化。
- 在类中,字段可以在声明时不初始化,因为引用类型的默认值是
null
。
- 适用场景:
- 结构体适用于小型数据结构,它们封装了少量的数据,且不需要扩展。
- 类适用于更复杂的数据结构,需要继承或需要在多个地方共享和操作同一个数据实例的场景。