The concept of delegates (references to methods) per se is new to me (although I used function pointers in C years ago), and although the literature acknowledges that there are significant differences between delegates and the use of pointers to objects, I'm nonetheless a little confused by how similar the syntax used for references to methods is to that used for references to objects.

Recently at a few different forums I posted a brief outline of my understanding of the instantiation of objects, and got corroboration and helpful feedback from several developers. Let me very briefly summarize my current understanding, for comparison to the way delegates work:

Steps to create and prepare to use an object:

1 Define a class: create a "blueprint" for objects of this class.

2 Declare an object: create a reference variable to hold a reference (address) of an object. The reference variable must be of the same class as the object.

3 Instantiate an object: allocate space for the object in the heap.

4 Assign an object to an object reference variable: place an object's address in an object reference variable.


Syntax used to implement these steps (numerals refer to the steps given immediately above):

1 Define a class:

class <class name> { < whatever > }

2 Declare an object:

<class name> <object name>;

3 Instantiate an object:

new <class name> ();

This is usually done within the same statement as assigning the object to an object reference variable (see immediately below), unless the object's reference (address) is being returned to some calling method.

3 & 4 Instantiate an object and assign it to an object variable within a single statement:

<object name> = new <class name> ();

2, 3 & 4 Declare an object, instantiate it and assign it to an object variable within a single statement:

<class name> <object name> = new <class name> ();

This seems very similar to how I understand delegates to work, which I've summarized below.

Steps to create and prepare to use a delegate reference:

1 Define a delegate type: specify the signature (including return type) of methods that delegates of this type can point to. This is called "declaring" the delegate; which I think is kind of confusing, since "declaring an object" means to create a reference variable to hold the reference (address) of an object (see step #2 above for objects), but in my opinion "declaring" the delegate is really much more analogous to defining a class (see step #1 above for objects).

2 Declare a delegate reference variable: create a delegate reference variable to hold the reference (address) of some methods. The delegate reference variable must be of the delegate type with the same method signature as the methods it will point to.

3 Instantiate a delegate: allocate space for a delegate in the heap. [BTW, what actually goes in the heap here - the reference (address) of a method, or a copy of the method?]

4 Assign the delegate to a delegate reference variable: place a method's address in a delegate reference variable.

Syntax used to implement these steps (numerals refer to the steps given immediately above):

1 "Declare" a delegate:

delegate <return type> <delegate identifier> (<parameter list>);

2 Declare a delegate reference variable:

<delegate identifier> <delegate name>;

3 Instantiate a delegate:

new <delegate identifier> (<method name>);

3 & 4 Instantiate a delegate and assign it to a delegate reference variable within a single statement:

<delegate name> = new <delegate identifier> (<method name>);

2, 3 & 4 Declare a delegate, instantiate it and assign it to a delegate reference variable within a single statement:

<delegate identifier> <delegate name> = new <delegate identifier> (<method name>);

Any feedback on my thoughts would be appreciated.

Your view of delegates and the mechanics of using them is very accurate.

Steps to create and prepare to use a delegate reference:

1 Define a delegate type: specify the signature (including return type) of methods that delegates of this type can point to. This is called "declaring" the delegate; which I think is kind of confusing, since "declaring an object" means to create a reference variable to hold the reference (address) of an object (see step #2 above for objects), but in my opinion "declaring" the delegate is really much more analogous to defining a class (see step #1 above for objects).

You are absolutely right. "Declaring a delegate" is exactly analogous to defining a class. If anything, I would object to the terminology of "declaring a delegate," and instead, when I need to speak uberprecisely, use the term "defining a delegate type." Whatever you call it, it's exactly analogous to defining a class.

3 Instantiate a delegate: allocate space for a delegate in the heap. [BTW, what actually goes in the heap here - the reference (address) of a method, or a copy of the method?]

What does the term "a copy of the method" mean? How does one "copy" a method? In any case, no copy of any method is made.

What goes on the heap are two things: a reference to the object you took the method from (unless it was a static method), and some way of identifying which method the delegate calls on the object. Creating a delegate is a fixed cost -- nothing expensive happens.

4 Assign the delegate to a delegate reference variable: place a method's address in a delegate reference variable.

Well it doesn't "place a method's address" in the variable, it places a reference to the delegate object on the heap, which contains the information described above. You couldn't just use a "method's address" alone -- you need the object the method was defined on.

Syntax used to implement these steps (numerals refer to the steps given immediately above):

I presume you're talking about C# 1.1 delegates, because there are new ways to create delegates in C# 2.0 and C# 3.0.

What goes on the heap are two things: a reference to the object you took the method from (unless it was a static method), and some way of identifying which method the delegate calls on the object.

What happens if it WAS static method? And what is the thing that is put on the heap that identifies which method the delegate calls on the object?

I presume you're talking about C# 1.1 delegates, because there are new ways to create delegates in C# 2.0 and C# 3.0.

I've got Visual C# 2008 Express version 9.0.30729.1 SP. I don't know how to get it to tell me what version of the compiler it has. Would you happen to know what version it has or how to make it tell me what version it has?

What happens if it WAS static method? And what is the thing that is put on the heap that identifies which method the delegate calls on the object?

I don't know or care, but for all intents and purposes it could be a string containing the name of the method (and implicitly through the delegate type, the types of its arguments). I mean, that's all the information it needs to work. But probably in reality it's a function pointer.

We're ignoring anonymous delegates, though, for which there is no method name and more than just an object -- there are variables captured in the delegate's scope.

But how they're actually implemented is an implementation detail. An anonymous delegate type is basically equivalent to an abstract class with one abstract method and nothing else.

I've got Visual C# 2008 Express version 9.0.30729.1 SP. I don't know how to get it to tell me what version of the compiler it has. Would you happen to know what version it has or how to make it tell me what version it has?

Yours supports C# 3.0 and .NET 3.5, the latest versions.

This article has been dead for over six months. Start a new discussion instead.