I was looking at the implemention of
Observable.FromEvent<TEventHandler, TEventHandlerArgs>(add, remove)
and I'm struggling to grasp how it works. Lets says that TEventHandler is the standard:
public delegate void EventHandler(object sender, EventArgs e);
then the code that is puzzling me is:
TEventHandler d = (TEventHandler) Delegate.CreateDelegate(
typeof (TEventHandler),
(object) new Action<EventArgs>(observer.OnNext),
typeof (Action<EventArgs>).GetMethod("Invoke"));
(n.b I've specialised this generic code to this specific example instance.)
How is it that CreateDelegate is creating a delegate of signature (obj, args) that is bound to an invoke method of signature (args) on the action? Where is obj going?
It feels a bit like it might be around having an open delegate on action and we are coercing the 'this' to be 'firstArguemnt' from CreateDelegate and allowing the args to fall through. If so feels kinda dirty?
Let's break it down:
Firstly, decompiling Rx v2.0.3 doesn't seem to have a Observable.FromEvent<TEventHandler, TEventHandlerArgs>(add, remove) method, and neither does Rx v 1.1 which I happened to have lying around. I'm going to assume you mean the nearest match I can find, which is this:
public static IObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>(Action<TDelegate> addHandler, Action<TDelegate> removeHandler)
Looking at the decompiled source for Rx 1.1 (the 2.0 source has gone all architecture astronaut on us and is full of indirection which makes it much harder to follow) The actual code snippet using reflector to decompile is this:
Action<TEventArgs> o = new Action<TEventArgs>(observer.OnNext);
TDelegate d = CreateDelegate<TDelegate>(o,
typeof(Action<TEventArgs>).GetMethod("Invoke"));
addHandler(d);
So, the question:
How is it that CreateDelegate is creating a delegate of signature (obj, args) that is bound to an invoke method of signature (args) on the action? Where is obj going?
I'm not sure if I've understood quite correctly, but it seems like the question specifically is something like How does CreateDelegate<TDelegate>(o, typeof(Action<TEventArgs>).GetMethod("Invoke") produce a method with only the args parameter - what happens to the o object?
What's happening is that yes, the o object is being passed as object firstArgument to the internal .NET framework method.
public static Delegate CreateDelegate(Type type, object firstArgument, MethodInfo method, bool throwOnBindFailure)
This method "binds" the firstArgument as basically being the this pointer for the returned method. Internally it will store a reference to the firstArgument somewhere inside the delegate object. We can't see inside that as it's an internal .NET implementation detail and so it can do all sorts of odd things and break rules where it pleases.
It feels a bit like it might be around having an open delegate on action and we are coercing the 'this' to be 'firstArguemnt' from CreateDelegate and allowing the args to fall through. If so feels kinda dirty?
Yes, that's pretty much exactly what's happening. This is what that CreateDelegate function is designed to do.
Except it gets even dirtier than that. CreateDelegate simply returns an object of type Delegate - we have no type safety on the method args, etc - and then the code casts it into a TDelegate - this works because delegate is special and you can cast it to any function type that has the same "shape". As above, it's an internal .NET implementation detail and so it can do all sorts of weird things :-)
Related
I have implemented a compiler and virtual machine for a language. The implementation is in C# and the stack-based VM uses reflection to make function calls on a set of built-ins.
Much of the code involves simply pushing and popping stack values, but the workhorse is the function call. Currently the implementation of a function call looks like this:
var calli = gencode[pc++] as CallInfo;
var calla = PopStackList(calli.NumArgs).ToArray();
var ret = calli.MethodInfo.Invoke(instance, calla);
if (ret != null) PushStack(ret);
All data items passed and returned are objects using a custom type system (no native types used). Clarification: this is an instance method, not static.
Performance testing suggests that this MethodInfo.Invoke is quite slow. The question is how to make function calls at the highest possible speed, presumably by doing more preparatory work in the compiler and generating better code.
In response to suggestions, one possibility is to create a delegate. Unfortunately as far as I can tell a delegate has to be bound to a specific instance of a class, or to a static method, and creating a delegate after creating the instance rather defeats the purpose.
I see a vote to close, but to my eye the question is not broad at all. How should a compiler implement functions calls on instance methods in a virtual machine for best performance, at the very least faster than MethodInfo.Invoke()?
Well, if you’re sure your main problem is MethodInfo.Invoke…
Use stuff from System.Linq.Expressions (Expression.Call, Expression.Parameter) to create an expression that calls that MethodInfo method, passing your parameters for instance + arguments.
Compile that expression into Action<tInstance, tArgs[]> (don't know your types of these).
Cache that Action in your CallInfo class instance.
Invoke that action as needed.
How to convert MethodInfo.Invoke to delegate:
Normally when you’re calling methods with reflection, you call MethodInfo.Invoke. Unfortunately, this proves to be quite slow. If you know the signature of the method at compile-time, you can convert the method into a delegate with that signature using Delegate.CreateDelegate(Type, object, MethodInfo). You simply pass in the delegate type you want to create an instance of, the target of the call (i.e. what the method will be called on), and the method you want to call. It would be nice if there were a generic version of this call to avoid casting the result, but never mind. Here’s a complete example demonstrating how it works:
using System;
using System.Reflection;
public class Test
{
static void Main()
{
MethodInfo method = (string).GetMethod(“IndexOf”, new Type[]{typeof(char)});
Func<char, int> converted = (Func<char, int>)
Delegate.CreateDelegate(typeof(Func<char, int>), “Hello”, method);
Console.WriteLine(converted(‘l’));
Console.WriteLine(converted(‘o’));
Console.WriteLine(converted(‘x’));
}
}
This prints out 2, 4, and -1; exactly what we’d get if we’d called "Hello".IndexOf(...) directly. Now let’s see what the speed differences are…
We’re mostly interested in the time taken to go from the main calling code to the method being called, whether that’s with a direct method call, MethodInfo.Invoke or the delegate. To make IndexOf itself take as little time as possible, I tested it by passing in ‘H’ so it would return 0 immediately. As normal, the test was rough and ready, but here are the results:
Invocation type Stopwatch ticks per invocation
Direct 0.18
Reflection 120
Delegate 0.20
Copied from: https://blogs.msmvps.com/jonskeet/2008/08/09/making-reflection-fly-and-exploring-delegates/
I am trying to desconstruct a method written by another coder to see how it works but it's getting a bit confusing
We have a Delegate that takes an Action as parameter.
private delegate void FunctionDelegate(Action next);
A function is then called in the constructor that takes an array of these delegates as parameter and executes each value in the array
LoadInSeries(LoadRoleAreaHours, LoadTableData);
The Function looks like this
private void LoadInSeries(params FunctionDelegate[] _delegates)
{
var Delegates = new List<FunctionDelegate>(_delegates);
Func<Action, Action> creator = null;
creator = delegate(Action inner)
{
if (Delegates.Count > 0)
{
FunctionDelegate L = Delegates.First();
Delegates.RemoveAt(0);
Action next = delegate { L(inner); };
return creator(next);
}
else return inner;
};
Action outer = creator(null);
if (outer != null)
outer();
}
The intent was too chain a series of functions with each function calling the next but wouldnt it just be easy to use a multicast delegate and add each function to the invocation list.
Does this code do something different?
Without a good Minimal, Complete, and Verifiable code example, it's impossible to understand the code fully. Of most significant concern is that your code example includes a mysterious L() method, the behavior of which we have no idea. There is also the problem with the FunctionDelegate = Delegates.First(); statement. At best, the FunctionDelegate identifier refers to a class field or property; at worst, that statement won't even compile. Either way, there's no evidence that the delegate object being removed from the input list is ever actually invoked.
So to even answer the question, some basic assumptions have to be made, which may or may not be correct.
That said, in the best-case scenario — which is that the code has hidden some awful, convoluted mechanism in the L() method that ultimately winds up able to invoke the delegate for the current call to the creator delegate — the code you're looking at is not simply invoking delegates in sequence, as would be the case with a MulticastDelegate. Rather, the code is constructing a chain of calls to the L() method, passing each delegate instance to the method in sequence.
Since you didn't show us the L() method, there's no way to say what the code actually does. I would agree that if all that L() does is invoke the delegate you pass to it, then this code looks like a very complicated way to just invoke an array of delegates. But, giving the benefit of the doubt to the person who wrote the code, this simply means that L() probably does something other than simply invoke the delegate.
Of course, it's possible the author of the code doesn't deserve the benefit of the doubt. In that case, not only would it be simpler to just use a multicast delegate, the simplest implementation would just iterate over the array, invoking each delegate in the desired sequence. But I say that without really knowing what the code does. I'm just assuming it's intended to do something useful with the delegates that are passed to it. There's no evidence in the code you posted to support even that generous assumption.
Give us the full picture, and a more definitive answer can be provided. Without knowing what L() is, or what side effects might exist in the passed-in delegates' target methods, it's impossible to say for sure whether the code you're looking at really needs to be written that way or not.
In C# I can do this:
delegate void myFunctionDelegate<T>(T arg);
In C++, I understand that I need to use an alias to a template for a function pointer, but the syntax is so bizaare that all of the examples I find just confuse me more.
The following is wrong; how can I correct it?
template<typename T>
using myFunctionDelegate = void (*)(T arg);
I want to use it like so:
template<class T> class Foo
{
...
void someOtherFunction(myFunctionDelegate callback)
{
...
callback(someValue);
}
}
and then:
myClassInstance.someOtherFunction([&](T arg) {
// do something with the callback argument
});
What you have almost works syntactically; the use of myFunctionDelegate simply needs a type argument:
void someOtherFunction(myFunctionDelegate<T> callback)
^^^
And the alias parameter names are optional if you aren't getting any particular benefit from them:
template<typename T>
using myFunctionDelegate = void(*)(T);
However, there is a larger problem: function pointers don't handle state. The lambda used in your sample call uses state by the capturing it does. Thus, a capturing lambda cannot be converted to a function pointer. When it's so handy to pass in such a lambda, function arguments should support that.
There are two common ways of doing so. The first is to forget about forcing a specific return and parameter type. Instead, let the caller pass any object (lambda, function pointer, functor, the result of std::bind) that can be called the way your function calls it:
template<typename Callable>
void someOtherFunction(Callable callback) {
...
callback(someValue);
}
If the call doesn't work, the code will fail to compile1 (with an error that unfortunately isn't too helpful, but the future Concepts additions can easily help there).
On the other hand, you might want to explicitly specify the function type. C++ has a general-purpose type to store any callable object (see the above list). That type is std::function. It's a bit more heavyweight than a simple template parameter, but useful when you need it.
template<typename T>
using myFunctionDelegate = std::function<void(T)>;
void someOtherFunction(const myFunctionDelegate<T> &callback) {...}
[1]: This isn't always true (see SFINAE), but it probably will be as far as you're concerned.
std::function<void(T)> myFunctionDelegate is the (very) rough equivalent of delegate void myFunctionDelegate<T>(T arg)
std::function<void(T)> follows value semantics (it behaves more like an int than a C# object reference) which makes things different.
A lambda closure ([](T t){/*code*/}) whose lifetime (or copies of it) outlives the local scope should not use & based capture. Instead use = based capture (which may require extra work). If the code you are calling does not store a copy of the delegate beyond the lifetime of the call, [&] is optimal. In C++ the lifetime of data is something you need concern yourself with.
This is not intended as a full tutorial on how lambdas and std::function work, but just to point you in the right direction.
I've been playing with HttpWebRequests lately, and in the tutorials they always do:
IAsyncResult result = request.BeginGetResponse(
new AsyncCallback(UpdateItem),state);
But new AsyncCallback doesn't seem to be necesary. If UpdateItem has the right signature, then there doesn't seem to be a problem. So why do people include it? Does it do anything at all?
It's the same thing, mostly (there are a few overload rules to think about, although not in this simple example). But in previous versions of C#, there wasn't any delegate type inference. So the tutorial was either (a) written before delegate type inference was available, or (b) they wanted to be verbose for explanation purposes.
Here's a summary of a few of the different ways you can take advantage of delegate type inferencing:
// Old-school style.
Chef(new CookingInstructions(MakeThreeCourseMeal));
// Explicitly make an anonymous delegate.
Chef(delegate { MakeThreeCourseMeal });
// Implicitly make an anonymous delegate.
Chef(MakeThreeCourseMeal);
// Lambda.
Chef(() => MakeThreeCourseMeal());
// Lambda with explicit block.
Chef(() => { AssembleIngredients(); MakeThreeCourseMeal(); AnnounceDinnerServed(); });
AsyncCallback is just a delegate in C#, it is declared as
public delegate void AsyncCallback(IAsyncResult ar);
When you pass the method name itself as long as the signature matches the compiler will usually substitute the code for you, its just shortcut.
You can simply check this using Reflector. If you have this for example.
request.BeginGetResponse(TestMethod, null);
static void (IAsyncResult r)
{
//do something
}
The compiled code will actually look like this.
request.BeginGetResponse(new AsyncCallback(Test), null);
For completeness, this changes between C# 1.2 (with .NET 1.1) and C# 2.0 (with .NET 2.0). So from 2.0 onwards you can indeed omit the new SomeDelegateType(...) in most scenarios. Oddly, the tooling hasn't changed, so in the IDE if you type someObj.SomeEvent += the IDE will suggest (via tab tab) the full version including delegate type.
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 use Delegate.CreateDelegate to create delegates via reflection. You can also use IL emit (DynamicMethod etc), but it isn't fun.
You first define the delegate (this is how Visual Studio knows the signature of the target method):
delegate void MyDelegate();
Then you construct delegate instances like this:
MyDelegate method = new MyDelegate({method name});
// If this was the method you wanted to invoke:
void MethodToInvoke()
{
// do something
}
MyDelegate method = new MyDelegate(MethodToInvoke);
C# automatically picks the method matching the signature of the delegate.
Edit: When Visual Studio's Intellisense shows you the int () target suggestion, it is showing you the signature of C# methods you can use. The C# compiler translates the C# representation to IL. The IL implementation will look different, because IL is not a C style language, and the C# compiler provides syntactic sugar to abstract away the implementation details.
This is just a guess, so don't shoot me if I'm wrong, but I think Intellisense is getting the signature for the target method from the Invoke method defined on the delegate. Reflector clearly shows that the Invoke method on System.Action<T> is:
[MethodImpl(0, MethodCodeType=MethodCodeType.Runtime)]
public virtual void Invoke(T obj);
Which is the same as the signature suggestion offered by Intellisense. The magic is Intellisense, when spotting a delegate type, looks at the Invoke method and suggests a constructor that takes a target that matches it.