[Gtk-sharp-list] widget destruction

Christopher David Howie me at chrishowie.com
Tue Mar 8 18:22:29 EST 2011


 On Mon, 7 Mar 2011 19:14:40 -0600, Mike Kestner wrote:
> seeing as I'm the
> only one who seems to think Dispose and Destroy actually mean two
> different things in the context of a C# binding to GObject.  It makes
> more sense to me that Destroy call Dispose, not vice-versa, and the
> using (FooDialog) pattern isn't all that compelling to me.

 I mostly agree with Lluis, but wanted to elaborate on a point and call 
 out another.

 Most people, AIUI, expect IDisposable.Dispose to release and destroy 
 all native resources held by an object.  Therefore it seems 
 counter-intuitive to me that Dispose() on a Gtk# widget would release 
 only the managed object and allow the unmanaged one to continue to live. 
 The only place where this makes sense, IMO, is when a managed object is 
 created to wrap a previously-created unmanaged object.  For people 
 familiar with .NET, they are going to expect "using(var foo = new 
 FooDialog())" to properly release all resources held by the new instance 
 of FooDialog, but in Gtk# 2 this is not the case.  IMO this is an API 
 design defect.

 As far as syntax goes, I find it hard to believe that you don't see 
 much difference between

 -----------------------8<-----------------------
     using (var foo = new FooDialog())
         foo.Run();
 -----------------------8<-----------------------

 And

 -----------------------8<-----------------------
     FooDialog d;
     try {
         d = new FooDialog();
         d.Run();
     } finally {
         if (d != null) {
             d.Destroy();
             d.Dispose();
         }
     }
 -----------------------8<-----------------------

 I know which one I would rather write...

 One compromise might be to have something hacky like this:

 -----------------------8<-----------------------
     public static class GtkObjectCoda
     {
         public static ObjectDestroyer<T> Destroyer<T>(this T self)
             where T : Gtk.Object
         {
             if (self == null)
                 throw new ArgumentNullException("self");

             return new ObjectDestroyer(self);
         }

         public struct ObjectDestroyer<T> : IDisposable
             where T : Gtk.Object
         {
             private T gtkObject;

             public T Object
             {
                 get
                 {
                     var obj = gtkObject;

                     if (obj == null)
                         throw new 
 ObjectDisposedException(GetType().FullName);

                     return obj;
                 }
             }

             internal ObjectDestroyer(T obj)
             {
                 Object = obj;
             }

             public void Dispose()
             {
                 var obj = Interlocked.Exchange(ref gtkObject, null);

                 if (obj == null)
                     throw new 
 ObjectDisposedException(GetType().FullName);

                 obj.Destroy();
                 obj.Dispose();
             }
         }
     }
 -----------------------8<-----------------------

 Then, on Gtk# 2:

 -----------------------8<-----------------------
     using (var foo = new FooDialog().Destroyer())
         foo.Object.Run();
 -----------------------8<-----------------------

 Meh.  It's not terrible, but having Dispose() do The Right Thing would 
 be better.

-- 
 Chris Howie
 http://www.chrishowie.com
 http://en.wikipedia.org/wiki/User:Crazycomputers

 If you correspond with me on a regular basis, please read this 
 document: http://www.chrishowie.com/email-preferences/

 PGP fingerprint: 2B7A B280 8B12 21CC 260A DF65 6FCE 505A CF83 38F5

 ------------------------------------------------------------------------
                     IMPORTANT INFORMATION/DISCLAIMER

 This document should be read only by those persons to whom it is 
 addressed.  If you have received this message it was obviously addressed 
 to you and therefore you can read it.

 Additionally, by sending an email to ANY of my addresses or to ANY 
 mailing lists to which I am subscribed, whether intentionally or 
 accidentally, you are agreeing that I am "the intended recipient," and 
 that I may do whatever I wish with the contents of any message received 
 from you, unless a pre-existing agreement prohibits me from so doing.

 This overrides any disclaimer or statement of confidentiality that may 
 be included on your message.


More information about the Gtk-sharp-list mailing list