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.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With