One more time - on delegates and garbage collection.

  • Thread starter Thread starter Daniel Billingsley
  • Start date Start date
D

Daniel Billingsley

Suppose I have a form FormA, and two objects ObjectB, and ObjectC.
ObjectC has an event SomethingChanged.
FormA has a reference to ObjectC.
FormA also instantiates an ObjectB object, passing it the ObjectC object and
one of its controls. (ObjectB stores those two references.)
ObjectB registers to handle the passed ObjectC's SomethingChanged event and
updates the passed control on FormA when it's fired.

(yes, roll-you-own data binding)

ObjectB doesn't need an explicit method to unhook from ObjectC, does it?
(I've seen code where it implements IDisposable and does it in Dispose.)

My understanding from when I asked this kind of question before was that the
only issue would be if ObjectB outlived ObjectC or FormA, as it would be
holding references to these objects that we really wanted to get collected.
In the arrangement as I described it, where ObjectB is no longer needed when
FormA is closed, I understand that everything will work fine.

Is my thinking right? If so, is there still an advantage to the explicit
unhooking?
 
Daniel Billingsley said:
Suppose I have a form FormA, and two objects ObjectB, and ObjectC.
ObjectC has an event SomethingChanged.
FormA has a reference to ObjectC.
FormA also instantiates an ObjectB object, passing it the ObjectC object and
one of its controls. (ObjectB stores those two references.)
ObjectB registers to handle the passed ObjectC's SomethingChanged event and
updates the passed control on FormA when it's fired.

(yes, roll-you-own data binding)

ObjectB doesn't need an explicit method to unhook from ObjectC, does it?
(I've seen code where it implements IDisposable and does it in Dispose.)

My understanding from when I asked this kind of question before was that the
only issue would be if ObjectB outlived ObjectC or FormA, as it would be
holding references to these objects that we really wanted to get collected.

Other way round, actually - if ObjectC was meant to outlive ObjectB, it
would still be holding a reference to ObjectB in its event handling
delegate.
In the arrangement as I described it, where ObjectB is no longer needed when
FormA is closed, I understand that everything will work fine.

Is my thinking right? If so, is there still an advantage to the explicit
unhooking?

Nope. I haven't experienced many occasions where I've needed manual
unhooking.
 
Jon Skeet said:
Other way round, actually - if ObjectC was meant to outlive ObjectB, it
would still be holding a reference to ObjectB in its event handling
delegate.

Uh, yeah, that's what I meant to say. :) Since this would all be on a form
it would be all or nothing for the whole lot.

I've actually gone a different direction, but along similar lines...

I've extended TextBox to listen to the object's SomethingChanged and update
this.Text. It overrides the OnTextChanged and updates the object's
property. Keystroke binding simple and easy.

So it is now referenced by the SomethingChanged hookup. But still, the
whole lot will go away with the form.

My question now is if I'm right thinking I still don't think I need to
override the TextBox.Dispose (as opposed to implementing it in the original
question) since I have nothing to add to the base class behavior in my
derived class. Right?
 
Daniel Billingsley said:
Uh, yeah, that's what I meant to say. :) Since this would all be on a form
it would be all or nothing for the whole lot.
Right.

I've actually gone a different direction, but along similar lines...

I've extended TextBox to listen to the object's SomethingChanged and update
this.Text. It overrides the OnTextChanged and updates the object's
property. Keystroke binding simple and easy.

So it is now referenced by the SomethingChanged hookup. But still, the
whole lot will go away with the form.

My question now is if I'm right thinking I still don't think I need to
override the TextBox.Dispose (as opposed to implementing it in the original
question) since I have nothing to add to the base class behavior in my
derived class. Right?

If I understand you correctly, that's right. Then again, I'm slightly
tipsy right now, so I wouldn't be too sure :)
 
Jon Skeet said:
If I understand you correctly, that's right. Then again, I'm slightly
tipsy right now, so I wouldn't be too sure :)

Suppose the object, ObjectA we'll say, isn't going to go away with the form,
but the TextBox of course is. Then I need to have the TextBox unhook from
the event so the ObjectA doesn't have a reference to it. Is it proper to
override the TextBox's Dispose in that case and put it in there, even though
technically it isn't an unmanaged resource. It seems to be the way to do it
according to the "Implementing a Dispose Method" in the MSDN library. Or
is it better to have a method, say Unhook, in the TextBox? That seems more
"proper" to me, but the Dispose seems simpler and safer on the other hand.

What actually happens in the case where for example a form creates ObjectA
and hooks it to an event in ObjectB and then the form closes taking ITS
reference to ObjectA with it? ObjectB keeps firing events... and the
handler code in ObjectA keeps running each time I guess, right? Suppose for
some reason that code in ObjectA crashes... what happens - a general
unhandled exception from the CLR?
 
Daniel Billingsley said:
Suppose the object, ObjectA we'll say, isn't going to go away with the form,
but the TextBox of course is. Then I need to have the TextBox unhook from
the event so the ObjectA doesn't have a reference to it.
Yes.

Is it proper to override the TextBox's Dispose in that case and put
it in there, even though technically it isn't an unmanaged resource.
It seems to be the way to do it according to the "Implementing a
Dispose Method" in the MSDN library. Or is it better to have a
method, say Unhook, in the TextBox? That seems more "proper" to me,
but the Dispose seems simpler and safer on the other hand.

I'm not sure what the best thing is there. It's sort of an abuse of the
Dispose method, but it's better than anything else we've currently got,
so I'd use it if I were you.
What actually happens in the case where for example a form creates ObjectA
and hooks it to an event in ObjectB and then the form closes taking ITS
reference to ObjectA with it? ObjectB keeps firing events... and the
handler code in ObjectA keeps running each time I guess, right? Suppose for
some reason that code in ObjectA crashes... what happens - a general
unhandled exception from the CLR?

If an exception is thrown from the event handler, that exception will
just propagate - the event is effectively just a series of delegate
calls.
 
Jon Skeet said:
I'm not sure what the best thing is there. It's sort of an abuse of the
Dispose method, but it's better than anything else we've currently got,
so I'd use it if I were you.

That's the way I was thinking.
If an exception is thrown from the event handler, that exception will
just propagate - the event is effectively just a series of delegate
calls.

Yeah but propagate to where? The code causing the exception is kind of
running in la-la land at that point.
 
Daniel Billingsley said:
Yeah but propagate to where? The code causing the exception is kind of
running in la-la land at that point.

It will propagate to whatever's calling the delegate, eg your
OnFooEvent method.
 
It will propagate to whatever's calling the delegate, eg your
OnFooEvent method.

Oh yeah, duh. Forget that events/delegates are just callbacks of a sort.
 
Back
Top