C#结构(Struct)

17.C#结构(Struct)——《跟老吕学C#》
C#结构(Struct)
一、结构体的定义
二、结构体的使用
三、注意事项
四、结构体与类的比较
五、结构体的高级用法
1. 结构体与接口
2. 结构体与装箱和拆箱
3. 结构体与常量
4. 结构体与互操作性
5. 结构体与布局控制
6. 结构体与只读字段
7. 结构体与嵌套结构体
总结


C#结构(Struct)
在C#中,结构体(Struct)是一种轻量级的值类型数据结构,它允许程序员将多个相关的变量组合成一个单一的类型。结构体在C#编程中扮演着重要的角色,特别是在需要封装少量相关数据,并且追求高性能的场景下。


一、结构体的定义
在C#中,结构体使用struct关键字进行定义,语法格式如下:

[修饰符] struct 结构体名
{
    // 字段
    数据类型 字段名1;
    数据类型 字段名2;
    // ...

    // 方法(可选)
    // C#中,结构体可以包含方法,但这些方法通常用于执行与结构体数据相关的操作
    // ...

    // 构造函数(可选)
    // 结构体也可以有构造函数,但只能是无参数的构造函数或带有初始化字段的构造函数
    // ...

    // 属性(可选)
    // 结构体也可以包含属性,以封装和访问其字段
    // ...

    // 索引器(可选)
    // 结构体可以定义索引器,以便通过索引访问其字段或进行其他操作
    // ...

    // 事件、接口实现等其他成员(可选)
    // 虽然不常见,但结构体也可以包含这些高级特性
    // ...
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

二、结构体的使用
在C#中,结构体通常用于表示具有少量数据且这些数据在逻辑上相关的简单实体。它们作为值类型在栈上分配(除非被装箱),这意味着当作为方法参数传递或赋值给另一个变量时,结构体会执行值拷贝操作,而不是引用拷贝。

下面是一个简单的结构体示例,表示一个二维点:

struct Point
{
    public int X;
    public int Y;

    // 构造函数,用于初始化结构体的字段
    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }

    // 方法,用于计算两点之间的距离(假设是二维平面上的点)
    public double DistanceTo(Point other)
    {
        var dx = X - other.X;
        var dy = Y - other.Y;
        return Math.Sqrt(dx * dx + dy * dy);
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
使用结构体的示例:

Point p1 = new Point(1, 2);
Point p2 = new Point(4, 6);
Console.WriteLine("Distance between p1 and p2: " + p1.DistanceTo(p2));
1
2
3

三、注意事项
结构体是值类型,与类(class)这种引用类型不同。
结构体通常用于表示简单的数据集合,而类则用于表示更复杂的对象和行为。
结构体可以包含方法、属性、构造函数等,但通常这些方法应该与结构体的数据紧密相关。
由于结构体是值类型,因此它们通常比类具有更好的性能,特别是在大量创建和销毁对象时。
结构体通常不应该用于封装复杂的行为或状态,这些应该由类来处理。
结构体在C#编程中提供了一种灵活且高效的方式来封装和操作相关的数据集合,特别是在需要高性能或简单数据表示的场景下。


四、结构体与类的比较
在C#中,尽管结构体和类在C#中都用于封装数据和相关操作,但它们之间存在显著的差异。以下是结构体与类之间的一些主要比较点:

类型:结构体是值类型,而类是引用类型。这意味着结构体在栈上分配内存(除非被装箱),而类在堆上分配内存。这种内存分配方式的不同,决定了它们在使用时的一些基本差异。

内存管理:由于结构体是值类型,它们通常不需要显式的内存管理(如new操作符和垃圾回收)。当结构体变量超出其作用域或被重新赋值时,其占用的内存会被自动释放。然而,类需要显式地创建实例,使用new操作符分配内存,并且当类实例不再被引用时,垃圾回收器会负责回收其占用的内存。

继承:类支持继承,这意味着一个类可以继承另一个类的属性和方法。这使得类在构建复杂层次结构时更加灵活,可以实现代码的重用和扩展。而结构体不支持继承(它们可以实现接口,但不能从其他结构体或类继承)。因此,结构体通常用于表示简单的数据集合,而不是复杂的对象层次结构。

默认构造函数:在C#中,类在没有显式定义构造函数时会自动获得一个默认的无参数构造函数。这个默认构造函数会执行一些基本的初始化操作,如将类的字段初始化为默认值。而结构体则不会自动获得默认构造函数,但可以在结构体中显式定义无参数构造函数或带有字段初始化的构造函数。这意味着在使用结构体时,需要更加注意其初始化操作。

性能:由于结构体是值类型,并且通常比类具有更小的内存占用,因此在处理大量数据时,结构体可能具有更好的性能。此外,由于结构体在栈上分配内存,访问速度通常比类更快。但是,这并不意味着在所有情况下结构体都比类更高效。在某些情况下,使用类可能更合适,因为它们提供了更多的功能和灵活性。

用途:类通常用于表示复杂的对象和行为,具有属性和方法来实现丰富的功能。类可以用于封装复杂的业务逻辑和数据操作,提供面向对象的编程范式。而结构体更适用于表示简单的数据集合,例如坐标点、颜色值等。结构体通常用于封装简单的数据结构和相关的操作,以提供高效的数据处理能力。

结构体和类在C#中都扮演着重要的角色,但它们在类型、内存管理、继承、默认构造函数、性能和用途等方面存在显著的差异。在选择使用结构体还是类时,需要根据具体的需求和场景进行权衡和选择。


五、结构体的高级用法
1. 结构体与接口
在C#中,结构体(struct)确实不支持类(class)所拥有的继承特性,但正如前面提到的,结构体可以实现接口(interface)。这种设计允许结构体定义与接口一致的方法和行为,从而极大地扩展了结构体的功能性和可重用性。例如,一个表示二维坐标的结构体Point可能实现了一个ICoordinate接口,该接口定义了计算两点间距离的方法。

2. 结构体与装箱和拆箱
在C#中,值类型(包括结构体)和引用类型之间存在明显的区别。当结构体作为值类型被当作引用类型使用时(如作为接口类型或object类型传递),会触发装箱(boxing)操作。这个过程会在堆上创建一个新的对象实例,并将结构体的值复制到该实例中。反过来,当从引用类型转换回值类型时,会发生拆箱(unboxing)操作。

虽然装箱和拆箱在某些情况下是必要的,但它们确实会带来一定的性能开销,因为涉及到内存分配和值复制等操作。因此,在编写高性能代码时,应尽量避免不必要的装箱和拆箱操作。

3. 结构体与常量
在结构体中,可以使用const关键字声明常量字段。这些常量字段必须在声明时初始化,并且它们的值在结构体的生命周期内保持不变。常量字段为结构体提供了在编译时定义固定值的能力,这对于那些需要固定配置或常数值的场景非常有用。

4. 结构体与互操作性
结构体在C#与其他编程语言或系统之间的互操作性中扮演着重要角色。在与C/C++代码进行交互时,结构体可以作为C/C++中结构体或联合体的映射。通过适当地定义结构体的字段和布局,可以在C#和C/C++之间实现跨语言的数据共享和函数调用。这种互操作性使得C#成为与现有C/C++代码库集成的理想选择。

除了与C/C++的互操作性外,结构体还可以用于与其他.NET语言或系统之间的交互。由于.NET框架支持跨语言互操作性(CLI),因此使用结构体定义的数据结构可以在不同的.NET语言中共享和使用。

5. 结构体与布局控制
在C#中,结构体的内存布局通常是由编译器自动管理的。然而,在某些情况下,可能需要更精细地控制结构体的内存布局以满足特定的需求(如与硬件接口交互或优化性能)。为此,C#提供了StructLayout属性来允许程序员指定结构体的内存布局。通过使用该属性,可以指定字段的顺序、对齐方式以及其他与布局相关的选项。

6. 结构体与只读字段
在某些情况下,可能希望结构体的某些字段在创建后不再改变。这可以通过将字段声明为只读(readonly)来实现。只读字段只能在声明时或在结构体的构造函数中进行初始化。一旦结构体被创建并初始化其只读字段后,这些字段的值就不能再被修改。这种特性有助于确保数据的一致性和安全性。

7. 结构体与嵌套结构体
在C#中,结构体可以嵌套在其他结构体内部。这种嵌套结构体的设计使得可以定义更复杂的数据结构,并将相关的数据组合在一起。嵌套结构体提供了一种组织代码和数据的方式,有助于提高代码的可读性和可维护性。同时,嵌套结构体还可以实现代码的重用和封装,从而提高代码的效率和质量。


总结
结构体在C#编程中提供了一种轻量级且高效的方式来封装和操作相关的数据集合。与类相比,结构体具有不同的类型、内存管理、继承支持、默认构造函数和用途。通过理解结构体与类之间的区别以及结构体的高级用法,程序员可以更好地利用结构体来提高代码的性能和可维护性。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/molangmolang/article/details/140070757

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值