文章目录
一、数据类型
1、类型分类
通用类型系统CTS(Common Type System)是.NET框架中的一个组成部分,为所有面向.NET框架的语言定义了数据类型的规则。
值类型: 存储数据本身。
引用类型∶存储数据的引用(内存地址)
2、类型归属
二、内存分配
1、内存
1、是CPU与其它外部存储器交换数据的桥梁。
2、用于存储正在执行的程序与数据,即数据必须加载到内存才能被CPU处理。
3、通常开发人员表达的”内存”都是指内存条。
2、分配
- 程序运行时,CLR将申请的内存空间从逻辑上进行划分。
栈区∶
----空间小(1MB),读取速度快。
----用于存储正在执行的方法,分配的空间叫做栈帧。栈帧中存储方法的参数以及变量等数据。方法执行完毕后,对应的栈帧将被清除。
堆区︰
----空间大,读取速度慢。
----用于存储引用类型的数据。
三、局部变量
定义在方法内部的变量。
特点:
----没有默认值,必须自行设定初始值,否则不能使用。
----方法被调用时,存在栈中,方法调用结束时从栈中清除。
1、值类型与引用类型
值类型:
声明在栈中,数据存储在栈中。
引用类型:
声明在栈中,数据存储在堆中,栈中存储该数据的引用。
2、分配图
3、垃圾回收器
GC(Garbage Collection)是CLR中一种针对托管堆自动回收释放内存的服务。
GC线程从栈中的引用开始跟踪,从而判定哪些内存是正在使用的,若GC无法跟踪到某一块堆内存,那么就认为这块内存不再使用了,即为可回收的。
四、成员变量
定义在类中方法外的变量·
特点:
----具有默认值。
----所在类被实例化后,存在堆中,对象被回收时,成员变量从堆中清除。
----可以与局部变量重名。
1、值类型与引用类型
值类型∶
声明在堆中,数据存储在堆中。
引用类型:
声明在堆中,数据存储在堆的另一块空间。
2、分配图
五、应用
1、比较
internal class Program
{
static void Main(string[] args)
{
int a = 1;
int b = 1;
Console.WriteLine(a==b);//结果为true
int[] arr1 = new int[] { 1 };
int[] arr2 = new int[] { 1 };
Console.WriteLine(arr1 == arr2);//结果为false
}
}
- 使用比较运算符比较值类型时,对比的是存储的数值。
- 比较引用类型时,对比的是引用的地址而不是数据。
2、赋值
internal class Program
{
static void Main(string[] args)
{
int a;
a = 1;
int b = a;//赋值的是数据
a = 2;
Console.WriteLine(b);//结果为1
int[] arr1;
arr1 = new int[1] { 1 };
int[] arr2 = arr1;//赋值的是索引
arr1[0] = 2;
Console.WriteLine(arr2[0]);//结果为2
}
}
3、传参
private static void Fun1(int a, int[] array)
{
a = 2;
array[0] = 2;
}
static void Main(string[] args)
{
int a = 1;
int[] arr = new int[] { 1 };
Fun1(a, arr);//执行完后从栈帧中消失
Console.WriteLine(a);//1
Console.WriteLine(arr[0]);//2
}
六、拆装箱
在 C# 语言中数据类型分为值类型和引用类型,将值类型转换为引用类型的操作称为装箱,相应地将引用类型转换成值类型称为拆箱。
1、装箱 box
值类型隐式转换为object类型或由此值类型实现的任何接口类型的过程。
内部机制:
1.在堆中开辟内存空间
2.将值类型的数据复制到堆中
3.返回堆中新分配对象的地址
- int 类型是值类型,而 string 类型是引用类型,当将值类型变量 a 的值转换成引用类型变量 str 时就是一个装箱的操作
int a=100;
string str=a.ToString();
2、拆箱 unbox
从object类型到值类型或从接口类型到实现该接口的值类型的显式转换。
内部机制:
1.判断给定类型是否是装箱时的类型
2.返回已装箱实例中属于原值类型字段的地址
- 而拆箱操作则是将引用类型变量 str 的值再转换成整型的过程
a=int.Parse(str);
3、实例
实例:利用装箱和拆箱功能,可通过允许值类型的任何值与 Object 类型的值相互转换,将值类型与引用类型链接起来
int val = 100;
object obj = val;
Console.WriteLine("对象的值 = {0}", obj);
//这是一个装箱的过程,是将值类型转换为引用类型的过程
int val = 100;
object obj = val;
int num = (int) obj;
Console.WriteLine("num: {0}", num);
//这是一个拆箱的过程,是将值类型转换为引用类型,再由引用类型转换为值类型的过程
4、注意事项
1.拆箱后的类型必须与装箱时的类型相同。
2.伴随拆箱的字段复制步骤不属于拆箱过程。
3.装箱和拆箱不是互逆的过程,装箱的性能开销远大于拆箱。