C# 结构体(Struct)
                           
天天向上
发布: 2025-04-13 13:31:54

原创
212 人浏览过

C# 结构体(struct)是一种值类型的数据结构,它在内存中分配空间时与类(class)不同。结构体通常用于封装较小的数据块,它有助于提升性能,特别是在大量对象创建的场景中。结构体的行为与类有很多相似之处,但它的内存管理和使用场景有所不同。


一、结构体的基本概念

  • 值类型:结构体是值类型(不像类是引用类型)。这意味着,当你将结构体赋值给另一个变量时,会创建该结构体的副本,而不是引用同一个对象。
  • 不能继承:结构体不能继承其他结构体或类,也不能被继承。
  • 自动包含无参构造函数:每个结构体都包含一个默认的无参数构造函数,但你不能自定义无参构造函数。可以定义带参数的构造函数。

二、定义结构体

结构体的定义类似于类,但用 struct 关键字来声明。

struct Point
{
    public int X;
    public int Y;

    // 带参数的构造函数
    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
}

三、创建和使用结构体

你可以像使用类一样创建和使用结构体,但结构体是值类型,因此它们的行为有所不同。

Point p1 = new Point(10, 20); // 使用带参数的构造函数
Console.WriteLine($"X: {p1.X}, Y: {p1.Y}"); // 输出 X: 10, Y: 20

Point p2 = p1; // 创建副本
p2.X = 30;     // 修改副本的值
Console.WriteLine($"p1.X: {p1.X}, p2.X: {p2.X}"); // 输出 p1.X: 10, p2.X: 30

✅ 结构体是值类型,所以修改 p2 不会影响 p1


四、结构体的常见操作

操作方法示例说明
newPoint p = new Point(5, 10);使用构造函数初始化结构体
ToString()point.ToString()返回结构体的字符串表示
Equals()point1.Equals(point2)比较两个结构体是否相等
GetHashCode()point.GetHashCode()获取结构体的哈希值

五、结构体的性能特点

  • 值类型分配在栈上:结构体实例通常分配在栈上,而类实例分配在堆上。栈的内存分配和回收速度比堆快,因此结构体可以避免堆分配的开销。
  • 避免垃圾回收:因为结构体是值类型,它们不需要垃圾回收(GC),这减少了运行时开销。

✅ 适合频繁创建、销毁的小对象(如坐标、颜色等)。


六、结构体的注意事项

  • 不可为 null:结构体是值类型,因此不能为 null,除非使用 可空类型(Nullable
Point? p = null; // 可空结构体
  • 不能继承:结构体不能继承其他结构体或类,也不能被继承。
  • 不能定义默认构造函数:结构体的默认构造函数是由编译器自动提供的,不能显式定义无参构造函数。

七、结构体示例:表示二维点

struct Point
{
    public int X;
    public int Y;

    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }

    public double DistanceTo(Point other)
    {
        return Math.Sqrt(Math.Pow(other.X - X, 2) + Math.Pow(other.Y - Y, 2));
    }

    public override string ToString()
    {
        return $"({X}, {Y})";
    }
}

使用结构体:

Point p1 = new Point(3, 4);
Point p2 = new Point(6, 8);

Console.WriteLine($"Point 1: {p1}");
Console.WriteLine($"Point 2: {p2}");
Console.WriteLine($"Distance: {p1.DistanceTo(p2)}");

八、结构体的比较与相等性

C# 默认会使用 逐字段比较 来判断结构体的相等性。你可以重写 Equals 方法来定义自定义的相等性比较。

struct Point
{
    public int X;
    public int Y;

    public override bool Equals(object obj)
    {
        if (obj is Point)
        {
            Point p = (Point)obj;
            return X == p.X && Y == p.Y;
        }
        return false;
    }

    public override int GetHashCode()
    {
        return X.GetHashCode() ^ Y.GetHashCode();
    }
}

九、结构体的适用场景

1. 简单的数据结构

适用于表示一组小的、封装的数据(例如:坐标、颜色、矩阵等)。

2. 性能优化

由于结构体是值类型,因此可以避免垃圾回收和堆内存分配的开销,特别是在频繁创建小对象时(例如:游戏开发中的位置、速度等物理属性)。

3. 线程安全

值类型(结构体)是线程安全的,因为每个线程处理的是独立的副本。


十、参考文献和文档


更多详细内容,请关注其他相关文章!

发表回复 0

Your email address will not be published. Required fields are marked *