richard
richard

Reputation: 12498

When an object calls one of it's own functions, is it a case of closure where the object is passed in as the first variable to the method?

I think I understand how closure is implemented in C# and .NET. When the CLR detects that a function will be passed outside its scope and acts on a free variable, it will package the function and the variable into a custom class.

So how is this different from what happens when an object calls one of its own functions? The object itself is passed into the function as the first variable so that if the function needs any of the object's other functions, properties, or fields, it has access to them.

I think I'm missing something here, and would like some sort of explanation of what is going on in both cases: closure, and the case where an object is calling one of its own methods.

Upvotes: 0

Views: 72

Answers (1)

Cosmin Prund
Cosmin Prund

Reputation: 25678

Normal method calls on an object has nothing to do with Closures; You only have a closure if you package that method call as a delegate!

In order to understand what's going on you need to have a good grasp on the concept of "value type" and "reference type". Talking about Object is not explicit enough in .net since Object is at the bottom of the hierarchy for everything, including value-types (int is also an Object). It's much easier to start thinking of method calls on pure reference types, like class instances.

Take your ordinary class variable and instantiation:

List x; // variable declaration
x = new List(); // instantiation

or, on a single line:

List x = new List();

The "body" of your instance will stay in a memory area that's called the Heap. The x that you're working with only holds a reference to that memory area, and that's why this is called a reference type.

When you call a method on the List using the x variable, the method needs to know on what list to work. So the method simply gets a reference to that body of the instance as the first parameter, the this parameter. It's incorrect to say the CLR or the Compiler passes "the object" because the object is always on the heap, it only passes a reference (or a pointer).

When the that method needs to call a different method of the same object, it simply passes the same this as the first parameter, the one it received itself.

A normal method call would look like this:

x.Add(Something); // calls instance method "Add" on "x"

When the compiler sees that it knows the reference to use x as the this (the first parameter, the hidden one) for the call to Add. There's no "closure" in there!

Here's what a closure would look like:

List<int> A = new List<int>();
List<int> B = new List<int>();

Action<int> aDelegate; // <-- declare a delegate type variable
                       //   Action<int> is a delegate that returns void and
                       //   takes a single int parameter.

aDelegate = A.Add; // <-- initialize the delegate using an instance method of object A
aDelegate(7); // <- notice the call! No reference to "A" because "A" is already stored in aDelegate

aDelegate = B.Add;
aDelegate(8); // <- notice the call! No reference to "B" because "B" is already stored in aDelegate

If you look closely at what happens when you call the delegate (aDelegate(7)), the compiler somehow needs to call the Add method on object A, but you can't see that, it's hidden. The delegate encapsulates both the reference to the object A and the address of the Add method and that's why it's called a closure. For contrast look at what happens when you do aDelegate(8); This time method Add is called on object B, but there's no way to guess that because again, the reference to object B was buried inside the delegate (the closure).

Upvotes: 1

Related Questions