写在前面
2022/11/05
C#数组的声明:
数组是一种引用类型,使用之前先声明
//声明一个字节类型的数组,数组中存放了4个元素,依次为0x01,0x02,0x04,0x0a
//注意:数组是由连续的内存位置组成的,也就是数组中的这四个元素在内存中的位置是连续的,如下图表所示,最低的地址存放第一个元素,最高的地址对应最后的元素
byte[] bt;
bt={0x01,0x02,0x04,0x0a};
byte[] bt;//这个时候会在栈中创建一个空间,地址占用4个字节,里面的内容这个时候是空null,这里只是引用地址的信息存放,
//实例化对象bt,堆中内存会给这个实例分配一个内存空间,这个bt占用两个字节,CLR公共语言运行库需要搜索一个未使用且连续的内存空间存储这个对象,2个字节,同时需要提供指针,把实例地址赋值给bt,如果没有连续的两个字节,会强制一次垃圾回收,如果回收后的空间还是不够,会抛出内存不足的异常。
bt={0x01,0x02};
上面的代码解释一下:byte[]这中类型是c#内置的数据类型,这种类型是引用类型,所以我们在用它的时就可以直接声明一个byte[]类型的变量bt,类似的还有int,string,ushort,uint,char等这些都是c#内部定义好的数据类型,有值类型和引用类型,而下面的委托和类类似,c#通过提供创建类的功能和创建委托的功能,让程序员可以自己创建数据类型,例如:
//创建一个类,类的类型为Student,为引用类型,
class Student
{
}
Student student;//创建了一个Student类型的变量student,首先这个变量的变量地址在栈中,
如果订阅了这个事件,当这个事件发生时候,就会执行订阅事件的方法。
如果订阅了这个事件,就会一直监视这这个事件。
一个事件可以多个订阅
定义一个变量int a;
a里面存放的为1
a地址的内存中存放的是1
a地址=&a,也就是指针,
定义一个方法 public int add(int a,int b)
这个add方法的地址是什么呢?
能不能有一个方法指针,&add就是这个值呢
那就是委托
delegate int add2(int a, int b)
add2 add3;
add3=add;
其实就是把add的地址给了add3,所以委托就类似于是方法指针
c#中变量的类型有值类型和引用类型,无论那种类型的变量都有变量的地址和值地址,
不论是那种类型的变量变量名(也就是变量地址)都是默认分配4个字节大小的内存空间,存放在栈里面,4个字节也就是32位,2的32次方为4g,系统会给一个进程分配的虚拟内存空间为4g,
值类型的内容也存放在栈里
例如:ushort a=2;//ushort占用2个字节
a的地址在栈中,假设0x00 01-0x 00 02-0x00 03-0x 00 04存放的是a,这4个字节内的内容也就是2的地址,假设2存放在0x00 00 55 56中,则在0x00 00 55 56-0x00 00 55 57的这两个字节中存放的是数字2的二进制,因为ushort的类型占用16位,所以这两个字节中为00000000 00000010
不同的是::注意::引用类型变量的地址在栈中占有4个字节,但是引用类型的值在托管堆中,因为c#这个语言有个GC垃圾回收机制,这个堆不像别的开发语言需要自己手动回收,而是自动回收,所以取名托管堆,所以引用类型只管使用,不用去考虑释放。
如果要使用委托,首先要定义委托类型,委托类型的定义和类的定义类似,委托的定义不用再创建一个文件,定义的委托类型为引用类型;
委托类型的变量存放的的是方法的地址,比如列表这种引用类型存放的是列表的首地址
delegate void mydelegate();
运行代码,在运行到14行的时候,st里面的内容为null也就是下图,4个字节的内存空间为null,因为是引用类型,st的地址有了,给它了四个内存空间存放内容,现在还没有内容,所以为null
接着运行:
st的值为123,这个时候下图4个字节的内存空间存放的不是123,而是123存放的地址,
![图片描述](https://img-blog.csdnimg.cn/3506caca96294aca9b8c801386fb2dad.png)
上图所示,st这个变量的变量地址为0x00 6f f2 38
0x00 6f f2 38
0x00 6f f2 39
0x00 6f f2 3a
0x00 6f f2 3b
这四个内存空间中存放着123的内存的首地址也就是0x02 9b 23 d8
添加一个值变量a,在运行到15行的时候,值变量a的值是0,这也是值变量和引用类型变量的区别,值变量默认空为0
建立了两个变量一个是a,一个是st
a的地址为
0x00 6f f2 34
0x00 6f f2 35
0x00 6f f2 36
0x00 6f f2 37
这里正好和st的首地址38连在了一起
而现在*&a是4