【问题标题】:How to write code to release manged/unmanaged resources in Destructor/Dispose method如何编写代码以在 Destructor/Dispose 方法中释放托管/非托管资源
【发布时间】:2019-08-02 11:42:55
【问题描述】:

我是 C# 的新手,我实际上了解析构函数和 dipose 方法的概念以及它们之间的区别以及实际上如何从这些操作中调用/阻止 GC。但是当我试图了解我们在这些方法中实际发布的内容时,我陷入了困境。

首先,仅仅定义一个空的析构函数或控制台输出不会对释放未使用的内存有任何好处。那么我应该在析构函数中写什么,或者将类的字段设置为 null 还是什么?我知道 GC 会处理托管资源,那么如果我遇到非托管资源怎么办

我通常在所有论坛和搜索中都能找到这个熟悉的示例,但没有人清楚应该写什么来释放未使用的内存

class Test : IDisposable
{
    private bool isDisposed = false;

    ~Test()
    {
       Dispose(false);
    }

    protected void Dispose(bool disposing)
    {
       if (disposing)
       {
          // Code to dispose the managed resources of the class
       }
       // Code to dispose the un-managed resources of the class

       isDisposed = true;
    }

    public void Dispose()
    {
       Dispose(true);
       GC.SuppressFinalize(this);
    }
}
& // 处理类的非托管资源的代码 )。谁能给我一个可以解决我疑问的示例

【问题讨论】:

  • 你不应该在析构函数中编写任何额外的代码,调用Dispose(false)就足够了。在// Code to dispose the managed resources of the class 之后,您应该处置您的托管资源(例如,调用MyManagedResourceInstance.Dispose())。在// Code to dispose the un-managed resources of the class 之后,你应该释放你的非托管资源(例如,释放系统句柄NativeMethods.CloseHandle(MyUnmanagedResourceHandle)
  • 不要尝试编写析构函数。编写正确的析构函数是 C# 中最难的事情之一,我强烈建议您不要这样做。如果您有需要管理的非托管资源,请使用安全句柄。有关正确编写析构函数很难的原因列表,请参阅ericlippert.com/2015/05/18/…
  • 对事物的工作原理感到好奇真是太好了,我鼓励这样做。但是你没有足够的经验来编写一个跟踪非托管资源的类。我已经编写 C# 程序十多年了,并且是编译器团队的一员,除了测试用例之外,我从未编写过析构函数。我不会尝试编写跟踪非托管资源的类,我鼓励您同样不要尝试。
  • 我看了这个问题,正要撕下评论...然后我看了看cmets,哇,总结得很好

标签: c# destructor finalizer disposable


【解决方案1】:

我了解示例,但注释中应该包含什么代码 线条

看,每个托管资源(即由 .Net 分配,在后台不使用非托管资源)都使用GC 释放,根本不需要处理。所有的处置都是关于unmanaged memory 那些通过 Win32 API 调用或任何非托管外部代码分配的。

现在回答你的问题,答案是你必须在Dispose 中释放那些非托管对象的代码,根据你正在使用的外部代码或API,应该有一种方法(例如方法)释放内存。

可能还有一个问题,既然只应该释放非托管代码,为什么会有一个部分来释放托管资源?
这是因为托管资源在内部依赖于非托管资源,通过调用 Dispose 您正在释放该内存,托管代码为您处理释放代码(包装在 Dispose 中)。这方面的例子可能是FileStream

【讨论】:

  • @vasily.sib,tnx 发表评论,编辑了我的帖子,我的意思是纯托管对象,不需要处理,对吧?
  • 作为一般规则,任何实现IDisposable 的类都应该被释放(except tasks)。如果类实例被暂时访问,这意味着将其包装在using block 中。如果实例是与该类共享生命周期的类的成员,则该包含类应实现IDisposable,并使用Dispose 方法处理任何IDisposable 成员。请注意,这些都不需要您编写析构函数。
猜你喜欢
  • 2015-05-27
  • 1970-01-01
  • 2020-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-18
相关资源
最近更新 更多