下面提供了两种方法来创建一个委托以设置类中的字段。其中一种方法使用泛型,另一种则不使用。
这两种方法都返回一个委托,并且它们都可以正常工作。但是如果我尝试使用在CreateDelegate方法内创建的委托,那么非泛型委托“del”能够正常工作。我可以在返回语句上放置断点并通过写入del(222)来调用该委托。但是,如果我尝试通过写入genericDel(434)来调用泛型委托“genericDel”,它会抛出以下异常:
“Delegate 'System.Action' has some invalid arguments”
有人可以解释这个怪异的现象吗?
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)
和b(5.0)
,它们都能正常工作。请注意,此代码是C# 4.0版本(其中引入了Expression.Assign
)。 - xanatosa()
和b()
的调用,所以代码可以直接进行测试。 - xanatos