C#_垃圾回收

一、GC机制

1、托管与非托管

托管资源就是托管给CLR的资源,CLR能对这些资源进行管理。CLR使用GC(Garbage Collector)来进行内存的管理,当检测到不需要的内存的时候就会自动释放。GC进行垃圾回收的时间我们无法确定,并且顺序也不能确定,除非手动调用GC.Collect()方法来通知运行环境立即进行垃圾回收。

非托管资源则是CLR无法对这些资源管理,这些资源的申请、释放必须由使用者自行管理。Stream,数据库的连接,GDI+的相关对象都是非托管资源。

2、什么是垃圾

我们知道,值类型分配在栈上,引用类型分配在堆上。分配在栈上的并不需要GC回收,分配在堆上的需要GC来完成内存的释放和回收。

当引用类型的对象没有任何引用的时候系统就认为它是垃圾。

3、对于非托管资源的释放,该怎么办呢

上面我们提到了,对于托管资源的释放回收,GC会自动进行,暂且不需要我们操心。那么对于非托管资源的释放呢,我们有两种方式:

3.1 Finalize方法

这里就需要补充一点关于析构函数的知识。

我们一般这样写析构函数:

class Car
{
    ~Car()  // destructor
    {
        // cleanup statements...
    }
}

其实,可以理解为如下代码:

protected override void Finalize()
{
    try
    {
        // Cleanup statements...
    }
    finally
    {
        base.Finalize();
    }
}

没有错,析构函数就是override了System.Object.Finalize方法。程序员是没有办法调用System.Object.Finalize方法,也没有办法调用析构函数。

析构函数只能被GC来调用,那么无法确定它上面时候被调用,因此用它作为资源的释放并不是很合理,因为资源释放不及时。值得一提的是,在关闭进程的时候,也会调用析构函数。

可能有人会说,不是也可以手动掉哦那个GC.Collect()吗?但是强制执行GC.Collect()会导致性能问题,并且回收顺序不确定,大多数情况下应避免这样做。

3.2 实现IDispose接口

上面介绍到使用析构函数是GC自动调用的,并不是我们期望的。如果需要手动释放资源,则需要实现IDispose接口。

官方链接

Dispose(bool) 方法的主体包含两个代码块:

  • 释放非托管资源的块。 无论 disposing 参数的值如何,都会执行此块。
  • 释放托管资源的条件块。 如果 disposing 的值为 true,则执行此块。 它释放的托管资源可包括:
    • 实现 IDisposable 的托管对象。 可用于调用其 Dispose 实现(级联释放)的条件块。
    • 占用大量内存或使用短缺资源的托管对象。 将大型托管对象引用分配到 null,使它们更有可能无法访问。 相比以非确定性方式回收它们,这样做释放的速度更快,此操作通常在条件块之外完成
    public class Person:IDisposable
    {
        ~Person() => Dispose(false);

        // Public implementation of Dispose pattern callable by consumers.
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);//不必执行析构函数
        }

        // Protected implementation of Dispose pattern.
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                // TODO: dispose managed state (managed objects).
            }

            // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
            // TODO: set large fields to null.
        }
    }

无参数的 Dispose 方法由该类型的使用者调用,因此其用途是释放非托管资源,执行常规清理,以及指示终结器(如果存在)不必运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值