On Aug 24, 2012, at 11:03 AM, James Lavery <ja...@microsec.co.uk> wrote:
> ResultSetConnection does /not/ subclass Java.Lang.Object. It is a plain C# 
> object.

A plain C# object with a finalizer [0]. You must be VERY CAREFUL when 
implementing finalizers:

        
http://msdn.microsoft.com/en-us/library/b1yfkh5e(VS.100).aspx#sectionToggle1
>       • An object's Finalize method should free any external resources that 
> the object owns. Moreover, a Finalize method should release only resources 
> that the object has held onto. The Finalize method should not reference any 
> other objects.

Emphasis on "external," which you should read as "unmanaged types." ResultSet, 
PreparedStatement, etc. are managed types, and thus their lifetime is 
controlled by the GC. Also note the last sentence, "The Finalize method should 
not reference any other objects."

FINALIZERS MUST NOT USE GC-CONTROLLED INSTANCES.

There is no ordering between finalizer invocation of instances [1]. 
Consequently, there is NO WAY to ensure that your ResultSetConnection instance 
is finalized _before_ the held e.g. ResultSet instance. What's probably 
happening to you is that the ResultSet instance is being finalized before your 
ResultSetConnection instance, and thus has it's Handle cleared out, so when you 
later attempt to call Close(), you're calling it on an invalid instance.

Again, Don't Do That™. In general, you should avoid finalizers, period, unless 
you really, _really_ can't avoid them.

 - Jon

[0] It's a "finalizer", not a "destructor": 
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf 
§17.12:

> [Note: In the previous version of this standard, what is now referred to as a 
> "finalizer" was called a "destructor". Experience has shown that the term 
> "destructor" caused confusion and often resulted to incorrect expectations, 
> especially to programmers knowing C++. In C++, a destructor is called in a 
> determinate manner, whereas, in C#, a finalizer is not. To get determinate 
> behavior from C#, one should use Dispose. end note]

[1] OK, there is _a_ way to ensure some form of finalizer ordering by using 
CriticalFinalizerObject [2]. However, this only provides a loose ordering 
between "normal" finalizable instances and critical finalizable instances -- 
the critical ones are finalized _after_ the normal ones -- but it does nothing 
about ordering between instances within the same "category."

This is still irrelevant, though, as Mono doesn't implement the "delayed" 
finalizer semantics for CriticalFinalizerObject.

[2] 
http://msdn.microsoft.com/en-us/library/system.runtime.constrainedexecution.criticalfinalizerobject.aspx

_______________________________________________
Monodroid mailing list
Monodroid@lists.ximian.com

UNSUBSCRIBE INFORMATION:
http://lists.ximian.com/mailman/listinfo/monodroid

Reply via email to