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.
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 useDelegate.CreateDelegate
to create delegates via reflection. You can also use IL emit (DynamicMethod
etc), but it isn't fun.