Hi James,
It looks like you have it right and I have a mistake in my writeup. Good pickup and analysis on your part, and I apologize for the time you must have lost trying to figure this out.
I wrote this article a number of years ago and was trying to come up with a single "FinalRelaseAnyComObject" method so that we would not have to worry about so many of the inner details involved with COM object releasing. The detail of releasing a COM object that has been hooked via VB.NET's 'WithEvents' keyword does not seem possible to encapsulate like this.
The issue is that when you use 'WithEvents', VB.NET places extra code to hook or unhook the events every time the
variable is set. Note that it does this for the
]variable in question, not the
object in question, which is how events are normally subscribed and unsubscribed. The result is that when creating the generic "FinalRelaseAnyComObject" method, the IL code generated can know which object is being acted on, but not which
]variable, so VB.NET
cannot add the special code to unhook the events from the 'WithEvents' variable in this case -- because the compiled IL code cannot know which variables are being acted on before hand. The fact that we are passing in the object
ByRef would
seem to handle this situation, but it does not because [c]ByRed[/i] allows us to reference the
object refernece in quesiton, but it still does not allow the compiler to know whether the variable being acted on is 'WithEvents' or not.
On the other hand, when you explicitly unhook your variable, the IL code can know whether that variable is using 'WithEvents' or not and so VB.NET adds the event unhooking code for you, allowing the COM object to be released.
I don't have the time right now to look at the IL code involved, but I do trust your results and, therefore, the explanation I've given here must be right. That said, if you take the time to look at the IL code for the two approaches that you've used, you'll see that the inline approach will have a couple of lines added by VB.NET that unsubscribe to the events, while the generic "FinalRelaseAnyComObject" method would not have these extra lines added by VB.NET.
I'll try to do this and report back next weekend about this (I have a very busy week ahead of me), but you can easily do this on your own by using
ILDASM or
Red Gate's Reflector, which are both free.
Hope this helps, James, and thanks for pointing it out!
Mike