Reputation: 549
Im trying to use create a func for double.CompareTo.
Im creating it like this:
var method = typeof(double).GetMethod("CompareTo", new Type[] { typeof(double) });
var func = (Func<double, double, int>)Delegate.CreateDelegate(typeof(Func<double, double, int>), method);
It works fine for string.CompareTo like this:
var method = typeof(string).GetMethod("CompareTo", new Type[] { typeof(string) });
var func = (Func<string, string, int>)Delegate.CreateDelegate(typeof(Func<string, string, int>), method);
I get an Argument exception saying That "the target method cannot be bound to since its signature or security transparency is not compatible with the delegate type" (freely translated from Swedish)
What is wrong?
Upvotes: 4
Views: 1441
Reputation: 1063198
IIRC the "extend the parameters and treat the first as the target" trick only works with reference types, such as string
- presumably because this instance method invoke becomes a static call with the address of the first argument, rather than simply loading the two arguments. You can hack around it - not very elegantly - via:
var dm = new DynamicMethod(nameof(double.CompareTo), typeof(int),
new[] { typeof(double), typeof(double) });
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarga_S, 0); // load "ref arg0"
il.Emit(OpCodes.Ldarg_1); // load "arg1"
il.Emit(OpCodes.Call, method); // call CompareTo
il.Emit(OpCodes.Ret);
var func = (Func<double, double, int>)dm.CreateDelegate(
typeof(Func<double, double, int>));
Or more simply, of course (although I suspect this won't help in the general case):
Func<double, double, int> func = (x,y) => x.CompareTo(y);
Upvotes: 3