C#对象的销毁和IDisposable

简介: 1.对象的析构函数与Finalize方法 与C++类似,C#允许程序员为类定义一个”析构函数“: class MyClass { ~MyClass() //析构函数 { //编写释放非托管的资源 } }  上面的代码编译后,可以看到: 这里调用了Object类的Finalize方法,这个方法里面是空的,什么也没有。

1.对象的析构函数与Finalize方法

与C++类似,C#允许程序员为类定义一个”析构函数“:

class  MyClass
{
    ~MyClass()  //析构函数
    {
         //编写释放非托管的资源
    }
}

 上面的代码编译后,可以看到:

这里调用了Object类的Finalize方法,这个方法里面是空的,什么也没有。

与构造函数类似,子类的析构函数会自动调用基类的析构函数,由此不断上溯,到最顶层的Object。上面显示了基类的析构函数是在finally里面执行的,这意味着销毁对象是先完成子类的清理工作,在完成基类的清理工作。如果基类没有定义析构函数,则跳过继续向上搜索。当CLR的GC要回收一个定义了析构函数的对象时,它会自动调用Finalize方法,而且调用Finalize方法的时机是不可控的,最好合适的方法就是让程序员主动以完全可控的方式去释放非托管的资源(例如文件句柄,数据库连接)。为此,.NET提供了IDisposable。

IDisposable接口只定义了一个Dispose方法,任何一个希望"手动"回收的非托管资源的类都应该实现该接口。

public interface IDisposable {void Dispose();},因为CLR认为这个接口就是一般的接口,所以不会主动调用。这需要程序员去调用。为了避免资源泄漏,可以这样:

    public class MyClass:IDisposable
    {
        ~MyClass()
        {
            Dispose();
        }

        public void Dispose()
        {
            //
        }
    }

Dispose方法应该允许被调用多次而不能引发异常。可以给出比较安全的代码框架:

            MyClass obj = new MyClass();
            try
            {
                //使用obj对象
            }
            finally
            {
                IDisposable disposable = obj as IDisposable;
                if (obj != null)
                {
                    obj.Dispose();//是否资源
                }
            }

C#提供了using关键来简化上述代码。using(MyClass obj=new MyClass()){//使用obj}

类的析构函数专用于清理非托管的资源,只有类需要提供一个在应用程序里面可随时调用的“显式”清理资源的功能时,才需要实现IDisposable,然而CLR的GC不会自动调用对象的Dispose()方法,只会调用Finalize方法(也就在析构函数里面)

IDisposable编程模式:

    public class MyClass : IDisposable
    {
        ~MyClass()
        {
            Dispose();
        }

        public void Dispose()
        {
            Dispose(true);//这样会释放所有的资源
            GC.SuppressFinalize(this);//不需要再调用本对象的Finalize方法
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                //清理托管资源
            }
            //清理非托管资源

        }
    }

读书笔记《.NET4.0面向对象编程漫谈》作者:金旭亮老师

相关文章
|
设计模式 消息中间件 安全
C# 一分钟浅谈:观察者模式与订阅发布模式
【10月更文挑战第11天】本文介绍了观察者模式和订阅发布模式,这两种设计模式主要用于实现对象间的解耦。观察者模式通过事件和委托实现一个对象状态改变时通知多个依赖对象;订阅发布模式则通过事件聚合器实现发布者与订阅者之间的解耦。文章详细探讨了这两种模式的实现方式、常见问题及避免方法,帮助开发者在实际项目中更好地应用这些模式,提升代码的可维护性和扩展性。
342 1
|
缓存 安全
预检请求(Preflight Request)
预检请求(Preflight Request)
940 3
|
算法
【算法】滑动窗口——将x减到0的最小操作数
【算法】滑动窗口——将x减到0的最小操作数
183 0
|
机器学习/深度学习 算法 开发工具
【YOLOv8量化】普通CPU上加速推理可达100+FPS
【YOLOv8量化】普通CPU上加速推理可达100+FPS
2455 0
|
机器学习/深度学习 文字识别 自然语言处理
分析对比大模型OCR、传统OCR和深度学习OCR
OCR技术近年来迅速普及,广泛应用于文件扫描、快递单号识别、车牌识别及日常翻译等场景,极大提升了便利性。其发展历程从传统方法(基于模板匹配和手工特征设计)到深度学习(采用CNN、LSTM等自动学习高级语义特征),再到大模型OCR(基于Transformer架构,支持跨场景泛化和少样本学习)。每种技术在特定场景下各有优劣:传统OCR适合实时场景,深度学习OCR精度高但依赖大量数据,大模型OCR泛化能力强但训练成本高。未来,大模型OCR将结合多模态预训练,向通用文字理解方向发展,与深度学习OCR形成互补生态,最大化平衡成本与性能。
6680 11
|
XML 机器学习/深度学习 数据格式
YOLOv8训练自己的数据集+常用传参说明
YOLOv8训练自己的数据集+常用传参说明
25770 3
|
算法 安全 定位技术
地图一共有多少个坐标系?有什么区别?如何选择?
地图一共有多少个坐标系?有什么区别?如何选择?
2577 11
|
Windows
解决“ACCESS_MASK不明确”错误
本文讨论了在编译过程中遇到的“ACCESS_MASK不明确”错误的原因和解决方法。错误通常由头文件冲突引起,解决方法包括去除自定义的命名空间、调整包含static函数的类头文件顺序,以及去除多余的#include指令。文章还提供了一些编程规范和参考链接。
677 1
|
缓存 人工智能 PyTorch
LMDeploy 部署 VLMs 的方法与探讨
LMDeploy 部署 VLMs 的方法与探讨 LMDeploy 是一个高效且友好的大型语言模型(LLMs)和视觉-语言模型(VLMs)部署工具箱,由上海人工智能实验室模型压缩和部署团队开发,涵盖了模型量化、离线推理和在线服务等功能。
LMDeploy 部署 VLMs 的方法与探讨
|
XML 存储 安全
C#开发的程序如何良好的防止反编译被破解?ConfuserEx .NET混淆工具使用介绍
C#开发的程序如何良好的防止反编译被破解?ConfuserEx .NET混淆工具使用介绍
1845 0