Gtk.Bin.Destroy()和Gtk.Bin.Dispose()有什么区别?

本文关键字:Gtk Bin 区别 什么 Destroy Dispose | 更新日期: 2023-09-27 18:06:32

我有一个gtk bin控件,我想删除它。这意味着我需要把它从操作记忆和窗口中移除。我通过简单地调用window. remove (child_item)来从窗口中删除它,但是我应该调用Destroy()或Dispose()还是两者都调用?按照什么顺序?

Gtk.Bin.Destroy()和Gtk.Bin.Dispose()有什么区别?

Dispose()是GObject的一部分,在实例结束序列中用于释放引用和分离信号处理程序;在引用循环的情况下,它可以被多次调用,因此检查未设置的字段是一个很好的做法。

Destroy()是GtkWidget的一部分,与Dispose()实现的目的类似;Destroy()在很大程度上是历史的产物,因为GObject最初是GTK的内部类型,然后才被移出(与类型系统的其余部分一起)到GLib中。在GtkWidget中,Destroy()作为Dispose()的默认实现的一部分被调用。

如果您想从容器中删除一个子对象,您可以简单地在容器上调用remove (child),或者在子对象上调用Destroy(): remove()将释放子对象上保存的引用,如果这是最后一个引用,这将导致小部件的销毁。在GtkWidget上调用Destroy()将导致小部件从其父容器中删除。这两个代码路径应该是可互换的。

直接调用Dispose()是Gtk -ism: Dispose()方法主要是为了被重写,而不是直接调用。

我查看了GtkSharp 3.24.24.34源代码。我检查了几个小部件,包括Bin和它的父部件,Dispose()Destroy()方法定义的唯一地方是Widget类。

如下所示,两种方法非常相似:

private bool destroyed;
protected override void Dispose (bool disposing)
{
    if (Handle == IntPtr.Zero)
        return;
    if (disposing && !destroyed && IsToplevel)
    {
        //If this is a TopLevel widget, then we do not hold a ref, only a toggle ref.
        //Freeing our toggle ref expects a normal ref to exist, and therefore does not check if the object still exists.
        //Take a ref here and let our toggle ref unref it.
        g_object_ref (Handle);
        gtk_widget_destroy (Handle);
        destroyed = true;
    }
    InternalDestroyed -= NativeDestroyHandler;
    base.Dispose (disposing);
}
public virtual void Destroy ()
{
    if (Handle == IntPtr.Zero)
        return;
    if (destroyed)
        return;
    gtk_widget_destroy (Handle);
    destroyed = true;
    InternalDestroyed -= NativeDestroyHandler;
}

我能看到的最大区别是Dispose()方法只对顶级小部件调用gtk_widget_destroy()函数,而根据Gtk文档,顶级小部件只有WindowInvisible。如果我理解正确的话,Dispose()方法(几乎)等于Destroy()方法,仅用于顶级部件,如Window

根据这个发现,当我想摆脱单个小部件时,我更愿意调用Destroy()方法,并将Dispose()方法留给窗口关闭时的最终清理,这是由垃圾收集器完成的。