在 C# 中,结构体(struct)和类(class)都是用于封装数据和行为的类型,但它们在多个方面存在显著差别,下面为你详细介绍:
- 结构体:是值类型。值类型变量直接存储数据的值,当把一个结构体变量赋值给另一个结构体变量时,会复制整个数据副本。结构体变量通常存储在栈上(如果是局部变量),不过当它作为类的成员时,会随类的实例存储在堆上。
- 类:是引用类型。引用类型变量存储的是对象在堆上的内存地址,而非对象本身。当把一个类的引用赋值给另一个引用变量时,两个变量指向堆上同一个对象实例,它们共享相同的数据。
// 结构体定义
struct PointStruct
{
public int X;
public int Y;
public PointStruct(int x, int y)
{
X = x;
Y = y;
}
}
// 类定义
class PointClass
{
public int X;
public int Y;
public PointClass(int x, int y)
{
X = x;
Y = y;
}
}
class Program
{
static void Main()
{
// 结构体使用
PointStruct struct1 = new PointStruct(1, 2);
PointStruct struct2 = struct1;
struct2.X = 3;
// struct1.X 仍为 1,因为是值类型复制
Console.WriteLine($"struct1.X: {struct1.X}, struct2.X: {struct2.X}");
// 类使用
PointClass class1 = new PointClass(1, 2);
PointClass class2 = class1;
class2.X = 3;
// class1.X 变为 3,因为引用同一对象
Console.WriteLine($"class1.X: {class1.X}, class2.X: {class2.X}");
}
}
- 结构体:
- 必须为所有字段赋值,即使不定义构造函数,编译器也会提供一个隐式的无参构造函数,它会将所有字段初始化为默认值。
- 不能定义无参构造函数,因为隐式的无参构造函数已经存在。
- 类:
- 可以定义无参构造函数,如果没有定义任何构造函数,编译器会提供一个默认的无参构造函数。
- 也可以定义带参数的构造函数,用于对类的成员进行初始化。
- 结构体:结构体不支持继承,不能从其他结构体或类继承,但它们都隐式继承自
System.ValueType 类。不过结构体可以实现接口。
- 类:类支持继承,可以从其他类继承并可以实现多个接口。一个类只能直接继承自一个父类,但可以实现多个接口。
- 结构体:结构体的字段如果不指定访问修饰符,默认是
private。不过一般建议显式指定访问修饰符。
- 类:类的成员如果不指定访问修饰符,对于类本身默认是
internal,对于类的成员默认是 private。
- 结构体:适用于表示轻量级的数据结构,如坐标、颜色、日期等简单的数据集合。由于结构体是值类型,创建和销毁的开销相对较小,在频繁创建和销毁实例的场景下性能较好。
- 类:适用于表示复杂的对象,需要维护状态和行为,并且可能涉及继承、多态等面向对象特性的场景。当需要创建大型、复杂且需要共享状态的对象时,使用类更为合适。