您的位置:首页 > 移动开发 > Unity3D

看书笔记——《Unity3d脚本编程使用C#语言开发跨平台游戏》——值类型和引用类型

2017-10-16 00:55 351 查看
引用类型

C#中大部分类型是引用类型,引用类型总是从托管堆中分配。

GUIContent guic = new GUIContent("按钮",texture);
其中new 做的事是:

1)计算所需要的内存空间,new操作符会计算目标类型和包括 System.Object 类在内的,其所有基类中定义的所有实例字段所需要的字节数。除此以外,为了方便Mono运行时管理对象,还有一些额外的信息需要托管对为其分配空间,如类型对象指针和同步索引块。

2)完成计算对象所需的空间后,就要为对象在托管堆上分配所需要的内存空间了。分配的所有字节都设为0

3)内存空间分配完,接下来需要初始化对象的“类型对象指针”以及“同步索引块”

4)当前3个准备步骤全部完成后,最后就要调用类型的实例构造器了。传递在使用new关键字时所指定的实际参数,例如上例中“‘按钮’,texture”以及“10,70,150,30”。此时编译器会在构造器中自动挡调用当前类型的基类构造器。每个类型的构造器都负责初始化该类型定义的实例字段。最终一定会调用 System.Object 的构造器,而构造器仅仅是返回,而没有什么个逻辑操作。

5)最后会返回指向新建对象的一个引用。也就是说新建的变量是一个指向某类型对象的引用,而非对象本身。在上例中的变量guic便是这样的角色。

引用类型总是从托管堆分配,而new操作符返回指向对象数据的内存地址。引用类型可以总结为:

1)存储引用类型对象的内存空间需从托管堆上分配;

2)每一个对象都有一些额外的成员为Mono运行时提供操作该对象的信息,因而堆上非陪空间时也要考虑到这些成员的空间,同时这些成员必须被初始化;

3)  对象中的其他字段的字节总是0;

4)由于并没有一个和new操作符相对应的delete操作符存在,因而对象的狐猴工作主要由垃圾回收机制,也就是GC来处理。那么显而易见的是当为新的对象分配空间时,有可能会面临没有空间可用的情况,那么就会触发垃圾回收。

值类型和引用类型最大的区别是:基于值类型的变量直接包含值。值类型的优势主要体现在提升日常开发中常用的、简单的类型的性能。

值类型的实例一般分配在线程栈上,并且不受垃圾回收机制GC作用的影响。

值类型不能派生出其他的类型,所有值类型都是隐式密封的(这么做是为了防止值类型用作其他类型的基类型),相对于引用类型,值类型的使用环节了托管栈的压力,并且减少了消耗巨大的垃圾回收的次数。

局部变量的值总是存储在线程栈上,引用类型实例和静态变量总是存储在堆上。

引用类型总是分配在托管堆上,值类型并不总是分配在线程栈上(一般是这样)。

如特殊情况,数组中的元素,引用类型中的值类型字段、迭代器块中的局部变量、闭包情况下匿名函数(lamda)中的局部变量。因为如果以上几种情况下值类型实例如果分配在线程栈上,有可能会出现线程栈中的方法已经调用结束,但是还会访问这些值的情况。即如果分配在线程栈上,有可能会随被调用方法的返回而被清除掉。因此他们被分配在托管堆上,以满足在方法返回之后还能够访问的要求。

值类型,大体分为:结构和枚举。

结构分为:数字型结构:常见System.Int32结构、System.Float结构、System.Decimal结构等。。。布尔型结构:常见有 System.Boolean。。。用户自定义的结构

DataTime是值类型,也有计算能力,因此,结构并不是轻量级的类,也不是既然是值类型,就没有必要提供像类那样的那么多塞方法和逻辑功能。

枚举常见有:System.IO.FileAttributes枚举、System.Drawing.FontStyle枚举。

所有的结构都是派生自抽象类型System.ValueType,而System.ValueType派生自System.Object。枚举的基类System.Enum也是从System.Value派生而来。

//tr的值是对TestRef类的实例的引用
TestRef tr=new TestRef(1,2);

//构造值类型实例,其内存空间在线程栈上分配
//tv的值就是TestVal结构本身
TestVal tv = new TestVal (1,2);
值类型的new关键字的作用仅仅是告诉编辑器该实例已经被初始化,如果不使用new关键字而仅仅是生命一个TestVal的实例,例如代码,

TestVal tv;编译器同样会为tv在线程栈上分配空间,并将其字段初始化为零,但是的注意,虽然事实上已经初始化,但是由于没有使用new关键字,因此并没有告诉编译器它已经被初始化的事实,如果单纯声明一个值类型变量,并且直接访问它,有可能会报错。使用了未赋值的字段。

1)值类型不派生出其他任何类型

2)值类型不需要从其他类型派生

3)值类型是不可变的。

4)值类型是以值方式传递的。值类型的主要优势是不是必须作为对象在托管堆上分配,但是如果值类型实例过大,也会由于复制的缘故,而对性能产生影响。

5)值类型实例有两种表示方式,未装箱和已装箱。

6)值类型派生自System.ValueType。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐