Dan Tao
Dan Tao

Reputation: 128317

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.

Upvotes: 10

Views: 1647

Answers (4)

Esben Skov Pedersen
Esben Skov Pedersen

Reputation: 4517

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

Upvotes: 4

itowlson
itowlson

Reputation: 74802

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

Upvotes: 10

Justin Grant
Justin Grant

Reputation: 46683

Yes, the delegate counts as a reference. Your object will not be garbage collected until the delegate is also unreachable.

Upvotes: 2

Grumdrig
Grumdrig

Reputation: 16977

If not, that sounds like a broken garbage collector.

Upvotes: 2

Related Questions