Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delegates in .NET: how are they constructed?

While inspecting delegates in C# and .NET in general, I noticed some interesting facts:

Creating a delegate in C# creates a class derived from MulticastDelegate with a constructor:

.method public hidebysig specialname rtspecialname instance 
   void .ctor(object 'object', native int 'method') runtime managed { }

Meaning that it expects the instance and a pointer to the method. Yet the syntax of constructing a delegate in C# suggests that it has a constructor

new MyDelegate(int () target)

where I can recognise int () as a function instance (int *target() would be a function pointer in C++). So obviously the C# compiler picks out the correct method from the method group defined by the function name and constructs the delegate. So the first question would be, where does the C# compiler (or Visual Studio, to be precise) pick this constructor signature from ? I did not notice any special attributes or something that would make a distinction. Is this some sort of compiler/visualstudio magic ? If not, is the T (args) target construction valid in C# ? I did not manage to get anything with it to compile, e.g.:

int () target = MyMethod;

is invalid, so is doing anything with MyMetod, e.g. calling .ToString() on it (well this does make some sense, since that is technically a method group, but I imagine it should be possible to explicitly pick out a method by casting, e.g. (int())MyFunction. So is all of this purely compiler magic ? Looking at the construction through reflector reveals yet another syntax:

Func CS$1$0000 = new Func(null, (IntPtr) Foo);

This is consistent with the disassembled constructor signature, yet this does not compile!

One final interesting note is that the classes Delegate and MulticastDelegate have yet another sets of constructors:

.method family hidebysig specialname rtspecialname instance void .ctor(class System.Type target, string 'method') cil managed

Where does the transition from an instance and method pointer to a type and a string method name occur ? Can this be explained by the runtime managed keywords in the custom delegate constructor signature, i.e. does the runtime do it's job here ?

EDIT: ok, so I guess I should reformulate what I wanted to say by this question. Basically I'm suggesting that there's not only C# compiler / CLR magic involved in delegate construction, but also some Visual Studio magic, since Intellisense flips out some new syntax when suggesting the constructor arguments and even hides one of them (e.g. Reflector does not use this syntax and construtor, for that matter).

I was wondering whether this assertion is true, and whether the function instance syntax has some deeper meaning in C# or is it just some constant format implemented by the Visual Studio magic part for clarity (which makes sense, since it looks like invalid C#) ? In short, if I was implementing Intellisense, should I do some magic for delegates or could I construct the suggestion by some clever mechanism ?

FINAL EDIT: so, the popular consensus is that that's indeed VS magic. Seeing other examples (see Marc Gravell's comment) of such VS behavior convinces me that that is the case.

like image 240
Saulius Valatka Avatar asked Mar 14 '10 20:03

Saulius Valatka


People also ask

How do you create a delegate?

A delegate can be declared using the delegate keyword followed by a function signature, as shown below. The following declares a delegate named MyDelegate . public delegate void MyDelegate(string msg); Above, we have declared a delegate MyDelegate with a void return type and a string parameter.

What is delegate how it is created in C#?

A delegate is a type that represents references to methods with a particular parameter list and return type. When you instantiate a delegate, you can associate its instance with any method with a compatible signature and return type. You can invoke (or call) the method through the delegate instance.

What is a delegate .NET framework?

Delegates in C# NET environment, a delegate is a type that defines a method signature and it can pass a function as a parameter. In simple words we can say delegate is a . NET object which points to a method that matches its specific signature.

Are delegates static C#?

Static delegates are not without limitations. They can only refer to static functions; member methods on objects are not permitted because there is no place to store the pointer to the object. Furthermore, static delegates cannot be chained to other delegates.


1 Answers

The first argument is resolved from the object reference (or null for static methods); no magic there.

Re the second argument, however - it is an unmanaged pointer (native int); in short, there is no alternative direct C# syntax that can use this constructor - it uses a specific IL instruction (ldftn) to resolve the function from metadata. However, you can use Delegate.CreateDelegate to create delegates via reflection. You can also use IL emit (DynamicMethod etc), but it isn't fun.

like image 58
Marc Gravell Avatar answered Sep 25 '22 12:09

Marc Gravell