目录
结构是值类型
● 结构是自定义类型,虽然与类相似,但是还是有区别的:
类是引用类型,而结构是值类型。 枚举也是值类型。
结构是隐式密封的,它们不能被派生。
结构类型的变量不能为null, 类是引用类型,类实例可以设置为null。
两个结构的变量不能引用同一个对象。
类的实例成员的内存分配是在堆中,而结构的实例成员内存分配是在栈中。
把一个结构的值赋值给另一个结构,就是将一个结构中的每一个实例成员的值一一对应的赋值给另一个结构的实例成员 ,这时,两个结构实例的都拥有自己的独立内存空间,更改一个结构变量的值不会影响另一个结构变量的值。
而复制类时,复制类变量时只复制引用。 那么这时,这个类变量都是指向同一个内存位置,更改一个类变量的值,会影响到另一个。
namespace Ch05Ex03
{
class CPoint
{
public int X;
public int Y;
}
struct Point
{
public int X;
public int Y;
}
class Program
{
static void Main(string[] args)
{
CPoint cs1 = new CPoint(), cs2 = null;
Point ss1 = new Point(), ss2 = new Point();
cs1.X = ss1.X = 5;
cs1.Y = cs1.Y = 10;
cs2 = cs1; //赋值类实例
ss2 = ss1; //赋值结构实例
ReadKey();
}
}
}
构造函数
● 结构可以有实例构造函数和静态构造函数, 但不能有析构函数, 因为它们的实例成员的内存都在栈中,又不是在堆中。
● 每一个结构都会有一个默认的构造函数,这个构造函数把结构的每一个字段设置为该类型的默认值。引用类型的字段初始化为null,数值类型字段的默认值初始化为0,布尔类型字段的默认值初始化为false,等等。
● 我们不可以在结构中创建默认的构造函数(带默认值的构造函数也叫默认构造函数),但是我们可以创建带参数的构造函数(不带默认值的)。 注意: 这和类不同,对于类; 只要类中声明了一个构造函数,编译器不再会生成一个默认值的构造函数,如果还想要默认构造函数,自己手动创建。 而在结构中,不管有没有其它构造函数,默认构造函数始终存在,而且不可以重新声明。
● 调用一个构造函数,包括默认的构造函数,都要使用new运算符, 即使不在堆中分配内存,也要使用new运算符。
● 也可以不使用new运算符创建结构的实例,但是有一些限制,如下:
在显式设置数据成员之后,才能使用它们的值。否则,不可以。
在对所有数据成员赋值之后,才能调用任何函数成员。
静态构造函数
● 与类相似,结构的静态构造函数创建并初始化静态数据成员,而不能引用实例成员。 结构的静态构造函数遵从与类的静态构造函数一样的规则。
● 以下两种行为,都会调用静态构造函数:
调用显式声明的构造函数,不管调用多少次构造函数,静态构造函数都只初始化一次。
引用结构的静态成员。
● 注意: 不可以在结构中声明字段,然后同时初始化字段。
● 注意:结构总是隐式密封的,所以它们不能派生其他结构。 由于结构不支持继承, 个别类成员修饰符用在结构成员上没有意义。 因此不能在结构成员声明时使用。 不能用于结构的修饰符如下:
protected
internal
abstract
virtual
那么结构本身派生于 System.ValueType, System.ValueType 派生自 Object.
两个可以用于结构成员并与继承相关的关键字是 new 和 override 修饰符。
结构作为返回值 和 参数
返回值 : 当结构作为返回值时, 将创建它的副本并从函数成员返回。
值参数 : 当结构被用作值参数时,将创建实参结构的副本。 该副本用于方法的执行中。
ref 和 out 参数 , 如果把一个结构用作 ref 或 out 参数 , 传入方法的是该结构的一个引用, 这样就可以修改其数据成员。