Erik83
Erik83

Reputation: 549

Delegate.CreateDelegate to get Func<> from MethodInfo does not work for double type?

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

Answers (1)

Marc Gravell
Marc Gravell

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

Related Questions