前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >C#小技巧|Dispose接口的正确使用方法

C#小技巧|Dispose接口的正确使用方法

作者头像
keyle
发布2024-11-01 12:21:13
发布2024-11-01 12:21:13
13400
代码可运行
举报
文章被收录于专栏:礼拜八不工作礼拜八不工作
运行总次数:0
代码可运行

我们知道在代码里自己写 Dispose 来释放一些资源。但是你真的用对了吗 ? 本篇介绍一些不容易注意到的 GC 相关知识 。

到底什么时候需要使用到 IDispose ?

当前类中出现 IO 操作。或者其他 跨语言调用,窗口和网络连接 之的非托管资源调用,这时才需要自己是实现一个IDispose 接口。其他的时候你并不需要去实现这样一个接口。我的做法是一般的类继承一个 IReset 接口,这个接口内只包含一个 Reset 函数 . Dispose 接口是一个显示的调用,如果我们没有写这个接口,运行时他会在执行析构函数的时候清理资源。

了解析构函数(终结器)

在使用Dispose 接口的同时 你或许同时会用到一个终结器。打个比方 如果你忘记显示调用 Dispose 函数的时候,程序还是会帮你清除非托管资源。

先观察以下析构函数

代码语言:javascript
代码运行次数:0
复制
class Car 
{
    ~Car()  // finalizer
    {
        // cleanup statements...
    }
}

上面的代码很简单,他等价于下面的代码

代码语言:javascript
代码运行次数:0
复制
protected override void Finalize()  
{  
    try  
    {  
        // Cleanup statements...  
    }  
    finally  
    {  
        base.Finalize();  
    }  
}  

现在你应该已经观察到这一行代码被隐式调用了,这行代码的意义是将当前运行时 Finalize 队列中创建一个条目,等待回收器来处理该队列。

代码语言:javascript
代码运行次数:0
复制
base.Finalize();  

正确的 “Dispose”

我们再观察下面的代码

代码语言:javascript
代码运行次数:0
复制
public class MyClass
{
    // 这里实现了IDispose中的 Dispose方法
    public void Dispose()
    {
        //执行资源释放 xxxxxxxx

        //告诉GC此对象的Finalize方法不再需要调用
        GC.SuppressFinalize(this);
    }

    ~MyClass()
    {
        Dispose();
    }
}

//下面我们使用using使用这个类
using(MyClass s = new MyClass()){}

上面我们使用了 GC.SuppressFinalize(this); 函数,他会告诉GC的Finalize队列中移除当前,不必在执行 Finalize()

注意事项

  1. 在非托管资源操作中才去重写dispose接口,否则使用其他自定义接口去实现 Reset 操作
  2. 在非托管资源操作中才去重写析构函数,否则空析构函数也会造成不必要的性能损失
  3. 重写dispose接口的同时别忘了重写析构函数

文外话

在 C# 语言里对析构函数与终结器的描述似乎是同一个东西,这让我有一点困惑。我查询了一些论文他们是这样说的。如果你感兴趣也可以看一下

In the C# world the terms “destructor” and “finalizer” seem to be used pretty much interchangeably, which I suspect is because the C# specification describes the non-deterministic cleanup functionality using the word “destructor”, whereas the CLR documentation always uses the word “finalizer”, so within the realms of C# they mean the same thing.

However, in the C++/CLI specification there is a distinction made between the two. It allows both deterministic and non-deterministic cleanup, and uses the term “destructor” for the deterministic functionality and “finalizer” for the non-deterministic functionality:

在C#世界术语“析构函数”和“终结”似乎要使用pretty多互换,我怀疑是因为C#规范用字“析构函数”,描述了非确定性的清理功能,而CLR的文档始终使用单词“终结”,所以C#的领域内,他们的意思是一样的。

然而,在C / CLI规范有两者之间作出区分。它同时允许确定性和非确定性的清理,并使用该确定的功能的非确定性的功能的术语“析构”和“终结”:

Microsoft 编程指南

https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/classes-and-structs/destructors

析构函数和终结器的区别?(The difference between a destructor and a finalizer?

http://www.it1352.com/382928.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-04-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 礼拜八不工作 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 到底什么时候需要使用到 IDispose ?
  • 了解析构函数(终结器)
  • 正确的 “Dispose”
  • 注意事项
  • 文外话
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档