02011101 结构
02011101 结构
1. 什么是结构
- 结构是程序员定义的数据类型,与类非常类似,结构也有数据成员和函数成员。
- 结构虽然与类类似,但是结构对比类有许多重要的区别如下。
- 类是引用类型,结构是值类型。
- 结构是隐式封闭的,这意味着不能从它派生其它结构。
// 声明结构的语法
struct StructName
{
...
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
using System;
namespace Demo01
{
struct MyStruct
{
public int X;
public int Y;
}
class Program
{
static void Main()
{
MyStruct myStruct01;
MyStruct myStruct02;
myStruct01.X = 10;
myStruct01.Y = 11;
myStruct02.X = 20;
myStruct02.Y = 21;
Console.WriteLine($"{myStruct01.X}, {myStruct01.Y}");
Console.WriteLine($"{myStruct02.X}, {myStruct02.Y}");
Console.ReadLine();
}
}
}
控制台输出:
10, 11
20, 21
2. 结构是值类型
- 和所有值类型一样,结构类型的变了含有自己的数据,因此:
- 结构类型的变量不能为null。
- 两个结构变量不能引用同一对象。(这句话没有理解,后续补充)
- 结构在内存中的分布。
类的内存安排与结构的内存安排
class CSimple
{
public int X;
public int Y;
}
struct Simple
{
public int X;
public int Y;
}
class Program
{
static void Main()
{
CSimple cs = new CSimple();
Simple ss = new Simple();
...
}
}
3. 对结构赋值
- 把一个结构赋值给另一个结构,就是将一个结构的值复制给另一个结构。注意,这和复制类变量不同,复制类变量时只复制引用。
类的内存安排与结构的内存安排
class CSimple
{
public int X;
public int Y;
}
struct Simple
{
public int X;
public int Y;
}
class Program
{
static void Main()
{
CSimple cs1 = new CSimple();
CSimple cs2 = null;
Simple ss1 = new Simple();
Simple ss2 = new Simple();
cs1.X = ss1.X = 5; // 将5赋值给ss1.X和cs1.X;
cs2.Y = ss2.Y = 10; // 将10赋值给ss2.Y和cs2.Y
cs2 = cs1; // 赋值类实例
ss2 = ss1; // 赋值结构实例
}
}
4. 构造函数和析构函数
- 结构可以有实例构造函数和静态构造函数,但是不能有析构函数。
4.1 实例构造函数
- C#隐式的为每个结构提供一个无参的构造函数。这个构造函数把结构的每个成员设置为该类型的默认值。
- 值成员设置成它们的默认值,引用成员设置成null。
- 对于每个结构,都存在预定义的无参构造函数,而且这个无参的构造函数不能删除或重定义。
- 注意,这里和类不同。对于类,只有在没有声明其它构造函数时提供隐式的构造函数。
4.2 不使用new运算符创建结构的实例
- 不适用new创建结构的实例有如下限制。
- 在显式设置数据成员之后,才能使用它们的值。
- 在对所有数据成员赋值之后,才能调用结构的函数成员。
using System;
namespace Demo01
{
struct MyStruct
{
public int X;
public int Y;
public MyStruct(int a, int b)
{
X = a;
Y = b;
}
}
class Program
{
static void Main()
{
MyStruct mys01 = new MyStruct(); // 通过new调用无参的构造函数,此时X和Y为默认值。
MyStruct mys02 = new MyStruct(10, 20); // 通过new调用有参的构造函数,此时X=10,Y=20。
Console.WriteLine($"{mys01.X},{mys01.Y}");
Console.WriteLine($"{mys02.X},{mys02.Y}");
MyStruct mys03; // @1 不通过new创建结构对象
mys03.X = 100; // @2
mys03.Y = 200; // @3
Console.WriteLine($"{mys03.X},{mys03.Y}"); // @4
Console.ReadLine();
}
}
}
控制台输出:
0,0
10,20
100,200
说明:在@1处不适用new运算符创建结构对象,必须在@2和@3处将所有数据成员赋值,然后才能在@4处使用结构对象。
4.3 属性和字段初始化语句
struct MyStruct
{
public int x = 0; // 编译错误
public int p1{get; set;} // 编译错误
static int z = 30; // 正确
static int p2(get; set;) = 5; // 正确
}
说明:
1. 在声明结构体时,不允许使用实例属性和字段初始化语句。
2. 在声明结构体时,结构体的静态属性和静态字段都可以在声明结构体时进行初始化。
4.4 结构是密封的
- 结构是隐式密封的,因此他不能派生其它结构。由于结构不支持继承,因此部分类的成员修饰符在结构成员上没有意义,因此不能在结构上使用,不能用于结构的修饰符如下:
- protected
- protected internal
- abstract
- sealed
- virtual
4.5 结构作为返回值和参数
- 当结构用作返回值时,将创建它的副本并从函数成员返回。
- 当结构作为值参数时,将创建实参结构的副本。该副本用于方法的执行中。
- ref和out参数,如果把一个结构用作ref或out参数,传入方法的是结构的一个引用,这样就可以修改其数据成员。
4.6 关于结构的更多内容
- 对结构分配的内存开销比类小,所以使用结构代替类有时可以提高性能,但是要注意装箱和拆箱的高昂代价。
- 预定义简单类型(int,short,long,等等),尽管.NET和C#中被视为原始类型,但是它们实际上再.NET中都实现为结构。
- 可以使用与声明分部类的方法声明分布结构。
- 结构和类一样,可以实现接口。
结尾
书籍:C#图解教程
著:【美】丹尼尔 · 索利斯;卡尔 · 施罗坦博尔
译:窦衍森;姚琪琳
ISBN:978-7-115-51918-4
版次:第5版
发行:人民邮电出版社
※敬请购买正版书籍,侵删请联系85863947@qq.com※
※本文章为看书或查阅资料而总结的笔记,仅供参考,如有错误请留言指正,谢谢!※

浙公网安备 33010602011771号