用到的知识才需要去深究
1.static 关键字
通过查看 IL 代码,我们会发现 static class 实际上就是 abstract sealed class
static class 还有一个限制,那就是只能从 System.Object 继承
2.递归
什么是递归函数/方法?
任何一个方法既可以调用其他方法又可以调用自己,而当这个方法调用自己时,我们就叫它递归函数或者递归方法!
通常递归有两个特点:
a.递归方法一直会调用自己直到某些条件满足,也就是说一定要有出口;
b.递归方法会有一些参数,而它会把这些新的参数值传递给自己;(自己调自己);
递归通常用于: ①.阶乘 ②.斐波拉切数列;
a.如果递归溢出后,会报异常
3.中间语言IL(Intermediate language)/CIL(Common Intermediate Language)公共语言运行(使用工具ILSpy)
过程:
C#源文件hello.cs------>通过C#编译器进行编译------>编译成.NET 的PE文件结构(exe文件格式)------>当程序运行时,Windows的Loader加载器不会负责该程序的内存分配,线程管理等工作,而是只负责跳转到CLR的执行引擎(EE)中,将控制权交由CLR,由CLR进行分配内存,线程管理,异常处理等
关键字:
.method表示方法的意思,.method private hidebysig static void Main(string[] args) cil managed表示的意思就是static void main(string[] args)
.entrypoint 标志方法的入口
.maxstack 表示分配堆栈大小
.localsinit中存放的是当前方法的局部变量,这里面是string类型,它的名称叫hello。Init指令表示对变量应以对应的类型默认值进行初始化,通常情况下变量名可以省略,在代码中将以零基索引来引用
先介绍几个关于MSIL内部知识点:
①.Managed Heap:这是动态配置(Dynamic Allocation)的记忆体,由 Garbage Collector(GC)在执行时自动管理,整个 Process 共用一个 Managed Heap,可以理解为引用类型的东西都放在这个Managed Heap中。
②.Call Stack:这是由 .NET CLR 在执行时自动管理的记忆体,每个Thread都有自己的Call Stack堆栈。每调用一次method,就会使得Call Stack上多了一个Record Frame;调用完毕之后,此Record Frame会被丢弃。一般来说,Record Frame内记录着method参数(Parameter)、返回位址(Return Address)、以及局部变量(Local Variable)。.NET CLR都是使用0, 1, 2…编号的方式来识别局部变量。
③.Evaluation Stack:这是由.NET CLR在执行时自动管理的记忆体,每个Thread都有自己专属的Evaluation Stack。压入的到Evaluation Stack的值,当方法调用结束时必须保持这个堆栈的平衡,这里面存放例如局部变量值,以及引用类型的地址。
指令ldc是将参数存储至堆栈Evaluation Stack
指令stloc是将变量存储至堆栈Call Stack
技巧:
ld开头就是加载数据到Evaluation Stack中,而st开头就是将Envaluation Stack中的数据保存到Call Stack,Call Stack存放局部变量值。
4.参数传递
当调用带有参数的方法时,您需要向方法传递参数。在 C# 中,有三种向方法传递参数的方式:
方式 描述
值参数 这种方式复制参数的实际值给函数的形式参数,实参和形参使用的是两个不同内存中的值。在这种情况下,当形参的值发生改变时,不会影响实参的值,从而保证了实参数据的安全。
引用参数 这种方式复制参数的内存位置的引用给形式参数。这意味着,当形参的值发生改变时,同时也改变实参的值。
输出参数 这种方式可以返回多个值。---按照用户输入的输出数据
个人理解:值传递是传递栈中的值,引用传递传递栈中的地址
5.数组
数组是一个引用类型,所以您需要使用 new 关键字来创建数组的实例。
一维数组
冒泡排序就是让一个数组中,从大到小或从小到大,使数组中的数不断互相交换位置来排序的方法。
注:命名空间下的类型可以为:Class、interface、delegate、struct、enum,不可以直接写变量和方法。