结构与枚举
首先,结构和枚举是值类型,对于结构和枚举的理解,需要对内存模型有一个很好的认识,众所周知,所有的类型分为值类型和引用类型,那么到底是值类型效率好还是引用类型效率好,为什么内存结构演化到今天任何一门语言的内存都有堆和栈的存在了。
值类型中有三种数据类型,结构、枚举、简单数值类型,首先我们来看结构,结构类型是一个轻量级的数据类型,一般用于存储简单的数据对象。注意、轻量级不等同于性能就好,结构与类相比,在不同的情况下各自有各自的性能优势,不能一概而论。(结构类型在传参和拷贝的时候性能不如类)结构默认继承自System.ValueType,即默认为值类型,通过IL代码可以得知,编译的时候结构和类是不区分的,在IL代码里面均为Class,此时内存还没有进行分配,从内存结构上暂时还无法进行区分,那么什么时候进行区分了,这就是运行时,即当代码执行的时候会进行区分,那么执行的时候是根据什么来进行区分的,根据就是,只要继承自System.ValueType的就是值类型,这里有一个很有意思的事情,System.ValueType本身是一个引用类型,通过查阅MSDN文档可以得知,它是一个抽象类,继承于它的类型是值类型,同时它也有一系列的成员,这就是意味着结构也拥有这些成员,有趣的是它所拥有的成员和System.Object是一样的,只不过是对system.ValueType中的几个虚函数进行了重写,这一点也说明System.ValueType继承自System.Object,现在我们知道了所有值类型均继承自system.ValueType,但是在定义的时候并不能进行显示的指定,例如:public struct data:ValueType,这种写法是错误的,当然更不能指定其它的类型。但是可以支持接口,总而言之,结构不能继承自除System.ValueType以外的其它类,同时也不能被其它类继承,因此面向对象的两大性质,继承和多态的特性它就没有了,没有了这两大特性,在使用的过程中就会受到很大的限制,所以结构类型在实际编程的过程中用到的不多,有时候当你设计一种数据结构的时不知道是该用结构还是类的时候,最好的做法就是不假思索的选择类。结构类型永远不是抽象的,并且始终是隐式密封的,因此在结构声明中不允许使用abstract和sealed修饰符。结构可以实现接口,但不能从另一个结构或类继承,而且不能作为一个类的基,所有结构都直接继承自 System.ValueType,后者继承自 System.Object。
下面我们看一段代码:
struct A
{
public int x; //不能直接对其进行赋值
public int y;
public static string str = null; //静态变量可以初始化
public A(int x,int y) //带参数的构造函数
{
this.x = x;
this.y = y;
}
}
class Program
{
staticvoid Main()
{
A a =new A(1,2);
A a1 = a;
a.x =10;
Console.WriteLine("a1.x={0}",a1.x);
Console.Read();
}
}
关于结构的构造器,结构不能声明默认构造函数(没有参数的构造函数)或析构函数,但可以声明带参数的构造函数。当定义带参数的构造函数时,一定要完成结构所有字段的初始化,如果没有完成所有字段的初始化,编译时会发生错误。
结构不能添加新的虚方法,原因很简单,结构不支持继承,也就不能有子类,因此结构中定义的虚方法就无法被重写,那结构中的虚函数就没什么意义了。但是有一点很值得注意,我们想一下,结构继承自System.ValueType,而System.ValueType又继承自System.Object,Object中有几个虚函数,因此结构可以去重写Object中的那几个虚函数,例如ToString函数,总而言之,结构不能定义新的虚方法,但是可以重写父类中的虚方法。
为什么结构不能自定义无参数的构造函数?
结构类型的构造函数与类的构造函数类似,用来初始化结构的成员变量,但是struct不能包含显式默认构造函数,因为编译器将自动提供一个构造函数,此构造函数将结构中的每个字段初始化为默认值表中显示的默认值。然而,只有当结构用new实例化时,才会调用此默认构造函数。对值类型调用默认构造函数不是必需的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库