Delegate Question: How does it know?

N

needin4mation

Learning about delegates (again, I admit), I think I finally get it,
maybe.

I can reference any method in any class in the same namespace as long
as it has the same signature. Right?

But how does it know? Does the .NET runtime keep a list of all the
possible methods that could be called and then when the delegate is
invoked, just look for a match? For example:

A very basic example (SimpleDelegate1.cs):

using System;

namespace Akadia.BasicDelegate
{
// Declaration
public delegate void SimpleDelegate();

class TestDelegate
{
public static void MyFunc()
{
Console.WriteLine("I was called by delegate ...");
}

public static void Main()
{
// Instantiation
SimpleDelegate simpleDelegate = new SimpleDelegate(MyFunc);

// Invocation
simpleDelegate();
}
}
}

Compile an test:

# csc SimpleDelegate1.cs
# SimpleDelegate1.exe
I was called by delegate ...

(taken from:
http://www.akadia.com/services/dotnet_delegates_and_events.html)

The system just "knows" to call MyFunc because it "knows" that delegate
can work with that type of method as defined by its signature?
 
S

sloan

Maybe this can help out.

This is the actual "register for an event" code.

The keyword being GetInvocationList





protected static MessageArrivalHandler m_handler;

public event MessageArrivalHandler MessageArrival
{
//when new handler is register for the event, start the listener
//if it is not yet started
add
{
m_handler += value;
}
remove
{
m_handler -= value;
//stop the listener if no handler is listed
if (m_handler == null || m_handler.GetInvocationList().Length <= 0)
{
//nobody is registered
}
}
}
 
N

Noah Sham

The delegate knows to call MyFunc because you told it to with the following
line of code.
SimpleDelegate simpleDelegate = new SimpleDelegate(MyFunc);
This code creates an instance of the SimpleDelegate class and that instance
stores the reference to the static method MyFunc.

What may be confusing is that this line of code
public delegate void SimpleDelegate();
is doing two things: declaring the method signature of the delegate void
(void) and declaring a class called SimpleDelegate which the compiler
derives from MultiCastDelegate. Check out
'http://msdn2.microsoft.com/en-us/library/system.delegate.aspx for a
detailed explanation.
 
F

Fao, Sean

If you look at a delegate as a pointer to a function (or in the case of
C#, a reference to a method) everything else should make sense.

Hope that helps,
 
J

Jon Skeet [C# MVP]

Learning about delegates (again, I admit), I think I finally get it,
maybe.

I can reference any method in any class in the same namespace as long
as it has the same signature. Right?

Namespaces are irrelevant. As of .NET 2.0, the signature doesn't have
to be exactly the same, just compatible.
But how does it know? Does the .NET runtime keep a list of all the
possible methods that could be called and then when the delegate is
invoked, just look for a match? For example:

No - when you create a delegate instance, you tell it which method you
want to call. It remembers.

See http://www.pobox.com/~skeet/csharp/events.html for a closer look at
events and delegates.
The system just "knows" to call MyFunc because it "knows" that delegate
can work with that type of method as defined by its signature?

No, it knows to call MyFunc because you've created a delegate instance
passing MyFunc as the parameter:

SimpleDelegate simpleDelegate = new SimpleDelegate(MyFunc);
 
B

Ben Voigt

Fao said:
If you look at a delegate as a pointer to a function (or in the case of
C#, a reference to a method) everything else should make sense.

Actually, although P/Invoke automatically compiles delegates into function
pointers, that may not be the internal representation of a delegate. By
reading the discussion of delegates and constrained execution regions
(http://msdn.microsoft.com/msdnmag/issues/05/10/Reliability/), it seems that
delegates are not pre-jitted.

So the original poster was very nearly correct. The runtime maintains a
list of all loaded methods (irregardless of namespace, and including all
assemblies). The delegate constructor checks the compatibility of the given
method (the C# compiler will do this in advance where possible), and stores
the metadata handle. Invoking the delegate causes the runtime to lookup the
method by its handle, JIT the MSIL if that hasn't been done yet, and then
run the native code generated by the JIT.

But nowhere does the runtime maintain a list of "methods compatible with
delegate type XYZ". It has a list of all methods, and enforces a subtype
constraint during compile or delegate construction (for construction by
reflection, see Delegate.CreateDelegate).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top