[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