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不会影响p1
Console.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、TimeSpanPoint、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# 中高效的值类型数据容器,适合存储小型、简单的数据。其核心特性包括:值类型存储、不能继承、无自定义无参构造函数等。使用时需根据数据大小和复杂度,在结构与类之间合理选择,以优化程序性能。
更多推荐


所有评论(0)