Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does a reference to a delegate constitute a reference to an object (to prevent garbage collection)?

I had trouble coming up with a good way to word this question, so let me try to explain by example:

Suppose I have some interface. For simplicity's sake, I'll say the interface is IRunnable, and it provides a single method, Run. (This is not real; it's only an example.)

Now, suppose I have some pre-existing class, let's call it Cheetah, that I can't change. It existed before IRunnable; I can't make it implement my interface. But I want to use it as if it implements IRunnable--presumably because it has a Run method, or something like it. In other words, I want to be able to have code that expects an IRunnable and will work with a Cheetah.

OK, so I could always write a CheetahWrapper sort of deal. But humor me and let me write something a little more flexible--how about a RunnableAdapter?

I envision the class definition as something like this:

public class RunnableAdapter : IRunnable {
    public delegate void RunMethod();

    private RunMethod Runner { get; set; }

    public RunnableAdapter(RunMethod runner) {
        this.Runner = runner;
    }

    public void Run() {
        Runner.Invoke();
    }
}

Straightforward enough, right? So with this, I should be able to make a call like this:

Cheetah c = new Cheetah();
RunnableAdapter ra = new RunnableAdapter(c.Run);

And now, voila: I have an object that implements IRunner and is, in its heart of hearts, a Cheetah.

My question is: if this Cheetah of mine falls out of scope at some point, and gets to the point where it would normally be garbage collected... will it? Or does this RunnableAdapter object's Runner property constitute a reference to the original Cheetah, so that it won't be collected? I certainly want that reference to stay valid, so basically I'm wondering if the above class definition is enough or if it would be necessary to maintain a reference to the underlying object (like via some private UnderlyingObject property), just to prevent garbage collection.

like image 772
Dan Tao Avatar asked Nov 12 '09 03:11

Dan Tao


2 Answers

Yes, that reference remains valid, and can in fact be retrieved using the Delegate.Target property -- in your code, as ra.Runner.Target.

like image 168
itowlson Avatar answered Sep 29 '22 11:09

itowlson


As others said it counts as a reference. You might find this story interesting. http://asserttrue.blogspot.com/2008/11/garbage-collection-causes-car-crash.html

like image 25
Esben Skov Pedersen Avatar answered Sep 29 '22 10:09

Esben Skov Pedersen