som*_*raj 27 .net c# garbage-collection finalizer suppressfinalize
我有几个问题,我无法得到正确的答案.
1)当我们没有析构函数时,为什么我们应该在Dispose函数中调用SuppressFinalize.
2)Dispose和finalize用于在对象被垃圾收集之前释放资源.无论是托管资源还是非托管资源我们都需要释放它,那么为什么我们需要在dispose函数中使用一个条件,当我们从IDisposable调用这个重写函数时传递'true':从finalize调用时Dispose并传递false.
请参阅我从网上复制的以下代码.
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);
}
}
Run Code Online (Sandbox Code Playgroud)
如果我删除布尔保护的Dispose函数并实现如下所示.
class Test : IDisposable
{
private bool isDisposed = false;
~Test()
{
Dispose();
}
public void Dispose()
{
// Code to dispose the managed resources of the class
// Code to dispose the un-managed resources of the class
isDisposed = true;
// Call this since we have a destructor . what if , if we don't have one
GC.SuppressFinalize(this);
}
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*eet 24
我的肢体会在这里,但是......大多数人并不需要全面的Dispose模式.它的设计是为了能够直接访问非托管资源(通常是通过IntPtr
)并面向继承.大多数情况下,这些都不是实际需要的.
如果您只是持有对其他实现的东西的引用IDisposable
,那么您几乎肯定不需要终结器 - 无论是什么保存资源都直接负责处理它.你可以做这样的事情:
public sealed class Foo : IDisposable
{
private bool disposed;
private FileStream stream;
// Other code
public void Dispose()
{
if (disposed)
{
return;
}
stream.Dispose();
disposed = true;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,这不是线程安全的,但这可能不会成为问题.
通过不必担心子类直接保存资源的可能性,您不需要抑制终结器(因为没有终结器) - 并且您也不需要提供自定义处理的子类方法.没有继承,生活就更简单了.
如果你确实需要允许不受控制的继承(即你不愿意打赌子类将有非常特殊的需求),那么你需要寻找完整的模式.
请注意,使用SafeHandle
.NET 2.0,您需要自己的终结器甚至比在.NET 1.1中更少.
为了解决为什么首先有一个disposing
标志的问题:如果你在终结器中运行,你引用的其他对象可能已经完成.你应该让他们自己清理,你应该只清理你直接拥有的资源.
以下是主要事实
1) Object.Finalize 是您的类在具有终结器时覆盖的内容。~TypeName() 析构函数方法只是“覆盖 Finalize()”等的简写
2)如果您在完成之前(即从 using 块等中出来时)在 Dispose 方法中处理资源,则调用 GC.SuppressFinalize。如果您没有终结器,则无需执行此操作。如果你有一个终结器,这可以确保对象从终结队列中取出(所以我们不会两次处理东西,因为终结器通常也会调用 Dispose 方法)
3)您将终结器实现为“故障安全”机制。终结器保证运行(只要 CLR 没有中止),因此它们允许您确保在未调用 Dispose 方法的情况下清理代码(可能程序员忘记在“使用”中创建实例)块等
4) 终结器很昂贵,因为具有终结器的类型不能在第 0 代集合(最有效)中进行垃圾回收,并通过 F-Reachable 队列中对它们的引用提升到第 1 代,因此它们代表一个GC 根。直到 GC 执行第 1 代收集,才会调用终结器,并释放资源 - 因此仅在非常重要时才实现终结器 - 并确保需要终结的对象尽可能小 - 因为所有可以您的可终结对象到达的对象也将被提升到第 1 代。
归档时间: |
|
查看次数: |
10040 次 |
最近记录: |