ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Unity基础—C#中Dispose和 Finalize

2022-06-17 22:05:29  阅读:211  来源: 互联网

标签:释放 调用 Finalize C# 托管 Dispose Unity GC


原文网址:https://zhuanlan.zhihu.com/p/390457469

要讨论这两个方法,首先要知道C#的 GC,因为有了 GC,所以开发者才能专注于应用程序的功能;然而 GC 也有局限性,它只能释放托管内存中的对象;像文件句柄,网络套接字,数据库链接这种非托管资源,GC 就无法帮你释放了。如果不释放这些资源,就会导致应用程序一直引用它们,而其他应用程序就无法对它们进行操作(比如:当你打开Word 文件,然后删除它的时候就会弹出:操作无法完成,因为文件已经在 Microsoft Office Word中打开)

C# 内的 Dispose() 和 Finalize() 方法,就是释放对象中非托管资源的方法。如果你想在自定义的类里面实现 Dispose() 方法,那么就得引用 IDisposable 接口;你可能见过使用 using 的代码,它其实就是try/finally格式的语法糖,在finally内会主动调用 Dispose() 方法,所以当你遇到非托管资源的操作,using是个很安全的做法。当然,你也可以在使用完该对象以后,主动调用它的 Dispose() 方法

using(FileStream file = new FileStream("path", FileMode.Open, FileAccess.Read))   
{  
    //Do something with file   
}

finailze() 是 object 类的内置方法;注意:你查看 object 类源码的时候,并不能查找到 finalize 方法,它是析构方法” ~Object() “编译产生的。如下图,析构方法 ~FinalizeTest() 编译成IL代码以后,就变成了 Finalize():

那么问题来了,既然有 Dispose() 方法,为什么还需要 Finalize() 方法呢? 因为有时候持有非托管资源的变量可能被用在很多地方,我们无法显示判断在何时调用 Dispose() 方法释放该资源。只有在 GC 的时候,我们判断引用该非托管资源的变量已经不被任何其他对象引用,这时候才是合适的释放时机。然而GC过程是内部实现的,我们无法在 GC 过程中手动调用 Dispose() 方法,所以 Finalize() 方法的用处就来了,GC 会自动调用 Finalize() 方法,我们只要把释放非托管内存的代码写在 Finalize() 方法中,就能释放非托管内存了

那么 Finalize() 是怎么被调用的呢? 当程序运行以后,GC会收集实现了 Finalize() 方法的对象,并把他们放入一个队列。当某个对象可以释放内存的时候:GC会把它所持有的非托管内存释放,并从队列中移除;但请注意,该对象在托管堆中并未释放。只有在下一次 GC 的时候,才会从托管堆中释放该对象

至此,我们已经了解了 Dispose() 和 Finalize() 方法,那是不是可以让他们两完美组合呢?既可以让用户手动调用,也可以做个托底,让GC自动调用。肯定可以的,代码如下:

using System;
public class FinailzeTest : IDisposable
{
    //GC自动调用
    ~FinailzeTest() { Dispose(false); }

    //用户手动调用
    public void Dispose() { Dispose(true); }

    protected virtual void Dispose(bool disposing)
    {
        //释放托管资源 
        if (disposing) { managedObject = null; }
        //释放非托管资源
        unManagedObjectDispose();
        //告诉GC, 把该类对象从列表中移除, 到时候不再执行Finalize()方法
        if (disposing)
        {
            GC.SuppressFinalize(this);
        }
    }
}

如果用户没有主动调用 Dispose() ,未能及时释放托管和非托管资源,那么在垃圾回收时,会执行Finalize(),释放非托管资源(注意:非托管资源并未被释放)
;如果用户主动调用了 Dispose(),就能及时释放了托管和非托管资源,而且垃圾回收的时候不会执行 Finalize() 方法,提高了性能

好了,关于 Dispose() 和 Finalize() 方法,就写到这,以后有新发现,再更新!

 

Finalize会阻碍析构函数的调用。

 

标签:释放,调用,Finalize,C#,托管,Dispose,Unity,GC
来源: https://www.cnblogs.com/bruce1992/p/16387118.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有