1

As far as I understand the concept of delegates, they simply point to a method. Then when I'm feeling lucky I can go out and invoke the method my delegate is pointing to, right?

Given is the following code:

class Program
{
    static void Main(string[] args)
    {
        Func<MyClass> myAct = GetAct();

        Method(myAct);
    }

    private static Func<MyClass> GetAct()
    {
        MyClass obj = new MyClass()
        {
            Prop1 = 5
        };

        Func<MyClass> myAct = new Func<MyClass>(
            () =>
            {
                MyClass obj2 = new MyClass();
                MyClass2 obj3 = new MyClass2()
                {
                    Prop3 = 25,
                    Prop4 = "test"
                };

                obj2.Prop2 = ((obj.Prop1 + 5) * obj3.Prop3)
                    .ToString() + obj3.Prop4;

                return obj2;
            });
        return myAct;
    }

    static void Method(Delegate func)
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();

        var result = func.DynamicInvoke();
    }
}

class MyClass
{
    public int Prop1 { get; set; }
    public string Prop2 { get; set; }
}

class MyClass2
{
    public int Prop3 { get; set; }
    public string Prop4 { get; set; }
}

Now my delegate myAct (in this case a Func<MyClass>) is pointing to an anonymous function which performs some simple assignation of variables. Nothing special so far.

We invoke the delegate.

Everything went fine, just as we expected. But the question is why? If the delegate just simply points to the anonymous method AND a garbage collection was done, how could the CLR know what obj and it's values are? Where is the reference to obj stored, to be available when the function is called? Inside the delegate?

GameScripting
  • 16,092
  • 13
  • 59
  • 98
  • 6
    See: http://stackoverflow.com/questions/428617/what-are-closures-in-net – Kirk Woll May 22 '12 at 18:30
  • 1
    I think the main problem is the base assumption that a delegate "simply point(s) to a method" is oversimplified. In fact, one delegate instance can hold references to multiple methods... – James Michael Hare May 22 '12 at 18:32
  • 1
    Also be aware of the pitfalls of using closures: http://msmvps.com/blogs/peterritchie/archive/2010/11/03/deep-dive-on-closure-pitfals.aspx – Chris Shain May 22 '12 at 18:33
  • @JamesMichaelHare in this case it does just point to a method. The method happens to be in a compiler-generated anonymous class that captures the current scope, but it is still a method. Multicast delegates are another issue altogether. – Chris Shain May 22 '12 at 18:34
  • @ChrisShain: I agree they are a different issue, I was just pointing out that thinking of them as a simple pointer to a method is not quite accurate. – James Michael Hare May 22 '12 at 18:37

1 Answers1

4

Your anonymous method is defined within the scope of GetAct() so CLR makes scope variables available to the anonymous method.

It's similar to how an instance variable is usable by member methods.

Also, review the pitfalls of using closures: http://msmvps.com/blogs/peterritchie/archive/2010/11/03/deep-dive-on-closure-pitfals.aspx

EtherDragon
  • 2,679
  • 1
  • 18
  • 24