1. C#中的as关键字,尝试进行类型转换,但是不抛出异常,比如
a) Dog dog = anAnimal as Dog;
上面代码如果转换不成功将dog赋值null
2. 装箱:将值类型变量装箱 使之成为对象类型。
3. 垃圾回收假设:
a) 最近被分配空间的对象最有可能被释放。
b) 生命期最长的对象需要释放的可能性最小。
c) 同时分配内存的对象同时被使用的可能性最大。
4. 分代的垃圾回收器(Generational Garbage Collector),最近被分配内存空间的对象被放在0代,因为很小,足以放到二级缓存(L2),所以可以快速存取。经过第一轮垃圾回收后,仍然在第0代的内存被放到第1代,之后……放在第2代。第2代包含了生存期较长的对象,这些对象经过了2轮回收。
5. 第0代的内存不足的时候,会自动触发第1代内存回收,将删除所有不再被引用的对象,并且将当前使用中的对象移到第1代。以此类推。
6. 垃圾回收的思想是很简单的。寻找不在使用的对象,将他们从内存中删除,并且压实托管堆以释放不再使用对象的内存。在堆被压实之后,所有的对象引用都被调整为指向对象新的存储位置。
7. 托管堆很高效,因为实现起来很简单。类似于简单的字节数组,有一个指向第一个可用内存空间的指针。同时分配的对象在托管堆上经常彼此相邻,而这种安排和传统的堆内存分配对象是完全不同的。传统堆上可能分配距离很远,从而降低了性能。因为L2内存很小,所以显然的,不能无限的这样分配下去。
8. 一般情况下,类可以提供那个终结器在对象被销毁的时候执行。原型为
a) protected void Finalize()
{
base. Finalize();
……;
}
b) 在用户执行上面代码之前,必须调用基类的终结器。也就是说
c) C#中,如果声明了析构函数,则不能同时存在终结器,因为两者完成的功能是等效的。
d) 注意:C#不能保证终结器或者析构代码会执行。.Net框架执行终结过程的方式使得他不能保证以即时的方式调用一个对象的终结器或者析构函数。在回收一个有终结器的对象的时候,不会将内存立即删除,而是将一个指向该对象的引用置入一个队列,这个队列包含的是等待终结的对象。
有一个专门的线程负责终结队列中的每个对象的终结器。然后该线程会将对象标记为不在需要终结操作并且将之从终结队列中删除。在终结操作完成之前,队列中的引用会确保对象存在,而在终结操作完成之后,对象将在下一轮的垃圾回收中被回收。
终结操作顺序是不确定的。当某个对象被终结的时候,他所引用的对象也许已经被终结了。在终结的过程中,用户可以安全的释放外部资源,如操作系统句柄或者数据库的连接。但是不应该再引用托管堆上的对象。
注意:任何时候应该避免创建终结器,因为开销很大。这些有终结器的对象通常会保留到两次或者更多的垃圾回收结束以后,从而增加了系统的压力。
不使用终结器的时候可以使用Dispose方法,释放用户资源。
如果使用了dispose方法,就应该调用GC. SuppressFinalize来告知运行的时候不需要终结此对象。如
Public void Dispose()
{
Toos.Dispose;
GC.SuppressFinalize(this);
}最好是在finally中调用,因为即使异常也要调用此部分代码。
如果类中有不会由托管堆分配的外部资源,那么即使已经实现了Dispose或者Close方法,还是需要另外实现一个终结器。理想的情况下,公开方法Dispose会以恰当的形式释放资源并禁止终结操作,从而有效的释放用户类占用的资源。即使哪个类忘记了Dispose,终结器也会被调用,作为确保类所使用的外部资源能够被释放的一张安全网。???
9. 使用IDisposablej接口:
Using (类 rc = new 类())
{
rc.Use();//用过之后自动调用Dispose
}
10. System.GC:包含有可能使得用户与垃圾回收机制进行相互操作的静态方法。包括发起新一轮的垃圾回收操作,确定某对象当前所在代的方法以及确定当前所分配的内存空间的方法。
a) Collect 在程序中发起新一轮垃圾回收。
i. 无参数 进行全面回收
ii. 整型参数 指定进行某代的回收
b) GetGeneration 指示第几代的垃圾回收
c) GetTotalMemory 返回托管堆上的内存空间总量。
i. 参数true:在计算托管堆大小之前进行一轮全面的垃圾回收。
ii. 参数false:不会进行回收活压缩任何未使用的控件。直接返回托管堆当前大小。