c#中结构体和类结构相似,够可以包括数据成员和方法成员。
二者区别:
1,结构是指类型,在栈中分配空间;类引用类型,在堆中分配空间,栈中保存引用。
2,结构直接存储成员数据,其成员数据位于堆中;类堆中保存对象,栈中的引用指向对象。
C#中的简单类型,如int、double、bool等都是结构类型。
由于结构是值类型,并且直接存储数据,因此在一个对象的主要成员为数据且数据量不大的情况下,使用结构会带来更好的性能。
一,struct --结构语法
结构:值类型,每个结构都保存自己的数据,修改一个结构数据不会影响其他结构。
类:多个引用可以指向同一个对象,对一个引用进行操作,必然会影响另一个,应该慎重。
二,结构赋值
创建结构赋给一个变量p1,则该变量包含结构的全部值。变量p1赋给变量p2时,将p1的全部值复制到p2的栈空间,p1的任何操作与p2无关。
将一个变量赋值给另一个变量时,是把数据从一个结构复制到另一个结构,当数据较多时,这种赋值机制开销较大。
类中变量间复制的是引用。
结构为值类型,不可赋null值。
三,构造函数
结构类型可以有实例构造函数和静态构造函数,但不能有析构函数。
1、实例构造函数
结构类型都有一个预定义的,没有参数的构造函数,这点与类是一样的。此构造函数不允许删除和重定义,并且这个无参数的构造函数会一直存在,并不会因为定义了其他带参数的构造函数就消失,这一点和类不同。
注意如果没有使用new运算符,是不可以使用数据成员的值(除非已显示地设置了该数据成员的值)和调用函数成员的(除非所有数据成员均已经被赋值)。
四,静态构造函数
和类一样,结构类型也可以有静态构造函数,静态构造函数用于初始化静态数据成员。静态构造函数有如下特点:
1、静态构造函数不能有访问修饰符和参数;
2、静态构造函数不能访问实例成员;
3、静态构造函数无法直接进行调用;
结构和类的静态构造函数的触发规则不同,类的静态构造函数是在创建第一个实例或引用任何静态成员之前自动调用的,而结构的静态构造函数在以下情况调用:
1、使用显式声明的构造函数进行初始化
2、调用结构的方法或访问结构的静态数据成员(无论是读取还是赋值,访问实例数据成员不会触发CLR自动调用静态的构造函数)。
五,结构的多态和可继承性
结构直接派生自System.ValueType,间接派生自System.Object,但结构是隐式密封的,不能作为基类在派生出其他的结构,也不能从类派生,但可以从接口派生。
结构的特性:
1、结构类型总是隐式密封的,因此在定义结构时不能使用sealed和abstract关键字;
2、因为结构不能作为基类,结构的成员不能使用如下访问修饰符:protected和protected,internal;
3、结构的函数成员不能声明为abstract和virtual,但是可以使用override关键字,用以覆写它的基类System.ValueType中的方法。
六,结构的装箱与拆箱
结构是值类型,因此当它被转换为object类型时,或者它所实现的接口类型的时候,就会执行装箱操作;同样,当执行相反操作的时候,就会执行拆箱操作。
七,结构和类的对比
结构 类
数据类型 值类型 引用类型
是否必须使用new运算符实例化 否 是
是否可声明无参数的构造函数 否 是
数据成员可否在声明的同时初始化 声明为const或static可以,数据成员不可以 可以
直接派生自什么类型 System.ValueType 有
是否有析构函数 无 有
可否从类派生 否 可以
可否实现接口 可以 可以
实例化时在栈还是在堆分配内存 栈 堆,栈中保存引用
该类型的变量可否被赋值为null 否 可以
可否定义私有的无参构造函数 否 可以
是否总有一个默认的无参构造函数 是 否
八,性能
因为结构是值类型,因此在为结构分配内存,或者当结构超出了作用域被删除时,性能会非常好,因为他们将内联或者保存在堆栈中。当把一个结构类型的变量赋值给另一个结构时,对性能的影响取决于结构的大小,如果结构的数据成员非常多而且复杂,就会造成损失,接下来使用一段代码来说明这个问题。
结构和类的适用场合分析:
1、当堆栈的空间很有限,且有大量的逻辑对象时,创建类要比创建结构好一些;
2、对于点、矩形和颜色这样的轻量对象,假如要声明一个含有许多个颜色对象的数组,则CLR需要为每个对象分配内存,在这种情况下,使用结构的成本较低;
3、在表现抽象和多级别的对象层次时,类是最好的选择,因为结构不支持继承。
4、大多数情况下,目标类型只是含有一些数据,或者以数据为主。