1

我已经阅读了这篇关于处理数据集的帖子,但我仍然对析构函数有疑问。我知道那个帖子基本上说你不需要处理数据集、数据表和数据视图,但是我的数据集是巨大的,所以我想尽快释放那个内存。所以,我的问题是,即使在调用我的对象的 dispose 方法时数据集将被释放,我是否应该包含一个析构函数?另外,再次向我解释为什么需要“布尔处理”。

        public DEditUtil(DataSet dsTxData)
    {
        this.dsTxData = dsTxData;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
                dsTxData.Dispose();

            disposed = true;
        }
    }

    ~DEditUtil()
    {
        Dispose(false);
    }
4

4 回答 4

4

是的,一般来说,只要满足以下任一条件,您就应该实现完整的 IDisposable 模式

  1. 您的班级正在分配非托管资源,或者
  2. 您拥有实现的托管资源IDisposable(这意味着它们又具有非托管资源)

终结器(C++/C# 称为“析构函数”的通用 CLR 术语)的存在是为了处理因某种原因未调用 Dispose 方法的情况。传递给受保护方法的布尔值Dispose()指示您是从 public 内部调用Dispose,还是从终结器内部调用。

如果您的公共Dispose方法被调用,则该调用堆栈是确定性的:您的 dispose 方法被直接调用,因此您可以安全地调用Dispose子对象上的方法(包括 )。

如果您在终结器内部,那么您不知道其他也被垃圾收集的对象发生了什么。通常,从终结器中调用您控制的托管对象上的方法可能不安全。

所以,布尔值基本上是说:“如果为真,则处置一切;如果为假,则仅处置我的非托管资源,让其他人处理他们的。”

于 2012-05-04T14:07:35.653 回答
2

对象使用的内存DataSet一旦不再被代码引用,就可用于垃圾回收。

垃圾收集器将在稍后(不确定的)时间将该内存提供给程序。

这两件事都不取决于是否有析构函数或对 的调用Dispose,所以答案是否定的——你不需要析构函数。

于 2012-05-04T14:07:26.257 回答
1

不,您在这里不需要任何其他方法调用,您所做的已经足够了。 Dispose将由运行时调用,您将释放分配的资源,清理让我们留给 GC 来决定如何以及何时进行清理。

如果你的内存真的有很大的问题,你可以尝试强制GC.Collect()收集垃圾,这通常是有效的,但以这种方式使用它从来都不是一个好习惯,所以尽量避免它。

编辑

根据评论,重要的是要注意您的情况下的执行流程,因为只有在不DataSet进行清理的情况下才会进行清理,并且从提供的代码来看,仅在代码的 esplicit 调用期间才会出现这种情况。disposed==falsedisposing == true

于 2012-05-04T14:05:39.973 回答
1

除了记录调用Dispose. 除非深入研究终结器如何工作的细节,以及关于它们运行的​​上下文的确切保证或不保证,否则永远不应该Dispose在终结器中调用任何其他对象的方法。特别是,如果一个对象的Finalize()方法正在运行,IDisposable它所引用的任何对象通常都属于以下类别之一:

  1. 其他人仍然拥有对该对象的引用并期望它可用,因此调用“Dispose”会很糟糕。
  2. 该对象无法在终结器线程上下文中安全地释放,因此调用“Dispose”会很糟糕。
  3. 如果它的 `Dispose` 处理程序有任何有意义的事情要做,那么该对象将保持当前对象处于活动状态;当前对象的 `Finalize` 方法正在运行的事实意味着不再需要在另一个对象上调用 `Dispose`(这种情况可能发生在事件中)。
  4. 该对象已经调用了它的`Finalize`方法,所以调用`Dispose`充其量是多余的。
  5. 该对象计划调用其“Finalize”方法,因此调用“Dispose”可能是多余的。

尽管在某些情况下,一个对象可能需要在方法中清理另一个IDisposable对象,但在这种情况下正确使用是很棘手的,并且使用不当往往比根本不使用更糟糕。除其他外,通常仅在实体请求并且在放弃之前错误地未能调用时运行。通常最好将精力集中在确保在放弃对象之前正确处理,而不是尝试正确处理有错误的消费者代码。FinalizeFinalizeFinalizeIDisposableDisposeDispose

于 2012-05-04T19:29:14.763 回答