1 C#中有两种类型:
值类型和引用类型:
值类型的变量直接包含他们的数据,引用类型存储对他们的数据的引用,后者称为对象:
简单说:值类型直接存储其值,引用类型存储对值得引用.引用类型分为引用和引用的对象。
2***、
值类型:简单类型、枚举、结构
引用类型: 类类型、接口类型、数组类型和委托类型、string
3***、值类型与引用类型的内存存储
单纯的说值类型存储在栈上,引用类型存储在托管堆上是不对的。
4***、区别:
1、
托管堆: 同步块和方法表, x,y,托管堆上的需要GC来回收
线程堆栈: 没有同步块和方法表
2、
值类型赋值是重新创建一个副本
而引用类型的赋值是共享同一块内存(副本),是指向同一块内存(引用类型的名字相当于指向操作)。只是复制引用而不复制被引用识别的对象。(“引用”和“引用的对象”)
3、
值类型与引用类型的不同之处就在于值类型的变量直接包括他们的数据,而引用类型的变量把references存储到他们的数据库(Objects)中。
4、
所有的值类型从Object中继承来的。任何类型都不能由值类型派生而来,因此,值类型是封闭式的。
5***什么时候使用值类型
1)当类型是一个十分简单的类型,其中没有成员会修改类型的任何实例字段
2)类型不需要从其他任何类型继承
3)类型不会派生出其他任何类型
4)类型的实例较小
5)类型不作为方法参数传递,也不作为方法的返回类型使用
6)引用类型可以包含null值,值类型不能(可空类型功能允许将null赋给值类型);
6***什么时候用ref和out
ref:值类型在传递希望成为引用的时候,ref就是告诉传递的时候不是拷贝,而是同一个副本。
out:不需要给变量赋初值,使用out也没必要在外面赋初值,是在内部赋“初值”,out传递值是理解成没有初始化的。
7***深度分析值类型和引用类型(内存中的部署)
例子:Objectreference r = new object();
关键字new在托管堆上分配内存空间,并返回一个该内存空间的地址。左边的reference位于栈上,是一个引用,存储着一个内存地址;而这个地址指向的内存(位于托管堆上)里存储着其内容。
规律:
1)引用类型部署在托管堆上
2)值类型总是分配在它声明的地方:作为字段时,跟随其所属的实例存储。作为局部变量时,存储在栈上。
总结: 引用类型在栈上存储一个引用,其实际的存储位置位于托管堆。
8***装箱与拆箱操作
1) 装箱操作
装箱(box)就是将值类型转换为引用类型的过程。而相反的过程就叫拆箱(unbox)。
装箱时发生了什么?
(1)在堆上分配内存。因为值类型最终有一个对象代表,所有堆上分配的内存量必须是值类型的大小加上容纳此对象及其内部结构(比如虚拟方法表)所需的内存量。
(2)值类型的值被复制到新近分配的内存中
(3)新近分配的对象地址被放到堆栈上,现在它指向一个引用类型。
2)拆箱操作
注:被装过箱的对象才能被拆箱。
在装箱的时候,并不需要显示类型转换.但在拆箱时需要类型转换.这是因为在拆箱时对象可以被转换为任意类型.
注意:装箱操作可以隐式进行,但拆箱操作必须显示。
首先,检查这个对象实例,看它是否为给定值类型的装箱值。
然后,把这个实例的值拷贝给值类型的变量。
要尽量减少装箱与拆箱操作
9***问题
1)C#中null和""的区别
string是引用类型:
string str= null 没有创建内存空间,str中存放的是空引用指针.
string str="" str中存放的是指向堆中的指针。有指向
简单地说:
string str ="";
给你一张白纸;
string str = null;
连白纸也没有。
string.Empty就相当于"" 一般用于字符串的初始化
判定为空字符串的几种写法,按照性能从高到低的顺序是:
s.Length == 0 优于 s == string.Empty 优于 s == ""
2)C#里面的垃圾回收
GC(垃圾回收)回收的都是可托管代码,也就是托管堆中的代码
一般定义一个引用变量,它肯定会在堆上面占用一块空间,栈上有个地址指向这个存储位置,只有当GC发现堆上这个资源在栈上没有地址指向它的时候才把这块内存回收。
非托管资源GC是不会自动回收的,例如数据库链接,文件等。