views:

80

answers:

4

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.

+1  A: 

If not, that sounds like a broken garbage collector.

Grumdrig
+1  A: 

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

Justin Grant
+5  A: 

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

itowlson
+3  A: 

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

Esben Skov Pedersen
Wow, that's... pretty darn definitive.
Dan Tao