Given below are two methods which create a delegate to set a field in a class. One method uses generics and the other does not. Both the methods return a delegate and they work fine. But if I try to use the delegate that has been created inside the CreateDelegate method, then the non-generic delegate 'del' works fine. I can place a breakpoint on the return statement and invoke the delegate by writting del(222). But If I try to invoke the generic delegate 'genericDel' by writting genericDel(434), it throws an exception:
Delegate 'System.Action' has some invalid arguments
Can anyone explain this quirk.
class test
{
public double fld = 0;
}
public static void Main(string[] args)
{
test tst = new test() { fld = 11 };
Type myType = typeof(test);
// Get the type and fields of FieldInfoClass.
FieldInfo[] myFieldInfo = myType.GetFields(BindingFlags.Instance | BindingFlags.Public);
var a = CreateDelegate<double>(myFieldInfo[0], tst);
var b = CreateDelegate(myFieldInfo[0], tst);
Console.WriteLine(tst.fld);
b(5.0);
Console.WriteLine(tst.fld);
a(6.0);
Console.WriteLine(tst.fld);
}
public static Action<T> CreateDelegate<T>(FieldInfo fieldInfo, object instance)
{
ParameterExpression numParam = Expression.Parameter(typeof(T), "num");
Expression a = Expression.Field(Expression.Constant(instance), fieldInfo);
BinaryExpression assExp = Expression.Assign(a, numParam);
Expression<Action<T>> expTree =
Expression.Lambda<Action<T>>(assExp,
new ParameterExpression[] { numParam });
Action<T> genericDel = expTree.Compile();
//try to invoke the delegate from immediate window by placing a breakpoint on the return below: genericDel(323)
return genericDel;
}
public static Action<double> CreateDelegate(FieldInfo fieldInfo, object instance)
{
ParameterExpression numParam = Expression.Parameter(typeof(double), "num");
Expression a = Expression.Field(Expression.Constant(instance), fieldInfo);
BinaryExpression assExp = Expression.Assign(a, numParam);
Expression<Action<double>> expTree =
Expression.Lambda<Action<double>>(assExp,
new ParameterExpression[] { numParam });
Action<double> del = expTree.Compile();
//try to invoke the delegate from immediate window by placing a breakpoint on the return below: del(977)
return del;
}
a(5.0)
andb(5.0)
and they work correctly. Be aware that this code is C# 4.0 (theExpression.Assign
was introduced there) – Cletacletia()
andb()
in your code, so the code is directly testable. – Cletacleti