C#中结构(Struct)
一、什么是结构(Struct)?
结构(struct
)是 C# 中一种值类型数据结构,用于封装小型相关数据。它与类(class
)类似,可包含字段、属性、方法等成员,但本质是值类型(存储在栈上),而类是引用类型(存储在堆上)。
核心特点:
- 值类型,赋值时直接复制数据(而非引用);
- 适合存储小型、简单的数据(如坐标、颜色、日期等);
- 不能被继承(密封类型),但可实现接口。
二、结构的定义语法
// 基本语法
访问修饰符 struct 结构名 : 接口1, 接口2...
{// 成员(字段、属性、方法、构造函数等)
}
示例:定义一个表示二维坐标的结构
public struct Point
{// 字段(通常私有,通过属性暴露)private int _x;private int _y;// 构造函数(必须初始化所有字段)public Point(int x, int y){_x = x;_y = y;}// 属性(封装字段,提供访问控制)public int X { get => _x; set => _x = value; }public int Y { get => _y; set => _y = value; }// 方法(定义行为)public void Move(int deltaX, int deltaY){_x += deltaX;_y += deltaY;}// 重写ToString()方法public override string ToString(){return $"({X}, {Y})";}
}
三、结构的核心特性
1. 是值类型,存储在栈上
- 结构的实例直接存储数据(而非引用),赋值时会复制完整数据。
示例:
Point p1 = new Point(1, 2);
Point p2 = p1; // 复制p1的所有数据到p2(值类型特性)
p2.X = 100; // 修改p2不会影响p1Console.WriteLine(p1); // 输出:(1, 2)
Console.WriteLine(p2); // 输出:(100, 2)
2. 不能有无参数构造函数
结构默认有一个隐式的无参数构造函数(由编译器自动生成),会将所有字段初始化为默认值(如
int
为 0,bool
为false
)。开发者不能自定义无参数构造函数(编译报错),但可定义带参数的构造函数,且必须在其中初始化所有字段。
// 错误示例:不能自定义无参数构造函数 public struct BadStruct {public BadStruct() { } // 编译报错:结构不能包含显式的无参数构造函数 }// 正确示例:带参数构造函数必须初始化所有字段 public struct GoodStruct {private int _a;private string _b;public GoodStruct(int a, string b){_a = a;_b = b; // 必须初始化所有字段,否则编译报错} }
3. 不能被继承(密封类型)
- 结构是
sealed
(密封)的,无法作为基类被其他结构或类继承,但可以实现接口。// 定义接口 public interface IMovable {void Move(int x, int y); }// 结构实现接口 public struct Point : IMovable {private int _x;private int _y;public Point(int x, int y){_x = x;_y = y;}// 实现接口方法public void Move(int deltaX, int deltaY){_x += deltaX;_y += deltaY;} }
4. 可以包含的成员
结构可包含与类类似的成员,但有一些限制:
- 允许:字段、属性、方法、构造函数(带参数)、索引器、事件、嵌套类型等。
- 不允许:无参数构造函数、析构函数(
~StructName()
)、protected
修饰符(因不能继承)。
5. 初始化方式
结构的实例化有两种方式:
使用
new
关键字:调用构造函数,初始化所有字段。直接赋值:不使用
new
,但必须先为所有字段赋值才能使用(否则编译报错)。// 方式1:使用new调用构造函数 Point p1 = new Point(1, 2);// 方式2:直接赋值(必须初始化所有字段) Point p2; p2.X = 3; // 错误:未初始化所有字段,不能使用 p2.Y = 4; // 正确:先赋值所有字段,再使用 而不是赋值属性 Point p3; p3.x = 3; p3.y = 4; Console.WriteLine(p3); // 输出:(3, 4)
四、结构与类的核心区别
对比项 结构(struct) 类(class) 类型 值类型(存储在栈上) 引用类型(存储在堆上) 赋值行为 复制所有数据(值传递) 复制引用地址(引用传递) 继承 不能被继承,可实现接口 可继承,可实现接口 构造函数 不能自定义无参数构造函数 可自定义无参数构造函数 默认初始化 隐式无参构造函数初始化所有字段为默认值 无参构造函数需手动定义(否则默认 null) 析构函数 不允许定义 允许定义(用于释放非托管资源) 适用场景 小型数据(如坐标、颜色、数值对) 复杂对象(如 Person、Order) 五、结构的使用场景
结构适合存储小型、简单、数据优先的实体,典型场景:
- 存储坐标或位置:如
Point
(x,y)、Rectangle
(宽、高、左上角坐标)。 - 表示数值类型组合:如
Currency
(金额、货币单位)、DateTime
(年、月、日)。 - 轻量级数据传输:如方法返回多个值时,用结构封装比用类更高效。
示例:系统内置结构
C# 中很多基础类型都是结构,例如:
int
(System.Int32
)、double
(System.Double
)DateTime
、TimeSpan
Point
、Rectangle
(System.Drawing 命名空间)
六、结构的性能考量
- 优势:作为值类型,结构在栈上分配和释放速度快,适合频繁创建和销毁的小型数据。
- 注意点:
避免定义大型结构(如包含多个字段或大数组),否则复制时会占用大量栈内存,导致性能下降(此时应改用类)。
结构作为方法参数传递时,默认是值传递(复制完整数据),若结构较大,建议用
ref
或in
关键字传递引用,减少复制开销:// 用ref传递结构引用(避免复制) void ModifyPoint(ref Point p) {p.X = 100; }Point p = new Point(1, 2); ModifyPoint(ref p); // 直接修改原结构,不复制 Console.WriteLine(p); // 输出:(100, 2)
七、常见问题解答
- Q:结构可以为 null 吗?
- A:默认不能。但可通过可空值类型(
Nullable<StructName>
或StructName?
)让结构为 null:Point? p = null; // 可空结构,p.HasValue 为 false p = new Point(1, 2); // 赋值后 p.HasValue 为 true
Q:结构的字段可以初始化默认值吗?
A:在 C# 10 及以上版本中,允许直接为结构的字段设置默认值:
public struct Point
{private int _x = 0; // 允许(C# 10+)private int _y = 0;
}
Q:结构和类如何选择?
A:遵循 “大小原则”:
- 数据量小(字段少且类型简单)→ 用结构;
- 数据量大或需要继承、复杂行为 → 用类。
八、完整案例:结构的综合使用
using System;// 定义表示颜色的结构(ARGB值)
public struct Color : IEquatable<Color>
{// 字段(带默认值,C# 10+支持)private byte _alpha = 255;private byte _red;private byte _green;private byte _blue;// 构造函数(初始化所有字段)public Color(byte red, byte green, byte blue){_red = red;_green = green;_blue = blue;// _alpha 有默认值,无需显式初始化}public Color(byte alpha, byte red, byte green, byte blue){_alpha = alpha;_red = red;_green = green;_blue = blue;}// 属性public byte Alpha => _alpha;public byte Red => _red;public byte Green => _green;public byte Blue => _blue;// 方法:判断是否与另一个Color相等public bool Equals(Color other){return _alpha == other._alpha &&_red == other._red &&_green == other._green &&_blue == other._blue;}// 重写ToString()public override string ToString(){return $"ARGB({_alpha}, {_red}, {_green}, {_blue})";}
}class Program
{static void Main(){// 创建结构实例Color red = new Color(255, 0, 0);Color transparentRed = new Color(128, 255, 0, 0);// 赋值(值复制)Color redCopy = red;Console.WriteLine(redCopy); // 输出:ARGB(255, 255, 0, 0)// 比较相等性Console.WriteLine(red.Equals(transparentRed)); // 输出:False// 可空结构Color? nullColor = null;Console.WriteLine(nullColor.HasValue); // 输出:False}
}
总结
结构是 C# 中高效的值类型数据容器,适合存储小型、简单的数据。其核心特性包括:值类型存储、不能继承、无自定义无参构造函数等。使用时需根据数据大小和复杂度,在结构与类之间合理选择,以优化程序性能。