umb*_*sar 4 c# generics lambda delegates expression
下面给出了两种创建委托以在类中设置字段的方法.一种方法使用泛型而另一种方法不使用泛型.这两个方法都返回一个委托,它们工作正常.但是,如果我尝试使用在CreateDelegate方法中创建的委托,那么非泛型委托'del'可以正常工作.我可以在return语句上放置一个断点,并通过写入del(222)来调用委托.但是,如果我试图通过书面方式genericDel(434)来调用泛型委托"genericDel",它抛出一个异常:
委托'System.Action'有一些无效的参数
任何人都可以解释这个怪癖.
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;
}
Run Code Online (Sandbox Code Playgroud)
我想我理解这个问题; 当委托的编译时类型是开放泛型类型时,您在从直接窗口调用泛型委托时遇到问题.这是一个更简单的复制品:
static void Main() { Test<double>(); }
static void Test<T>()
{
Action<T> genericDel = delegate { };
// Place break-point here.
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我尝试从Test方法中执行此委托(通过放置断点并使用立即窗口),如下所示:
genericDel(42D);
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
Delegate 'System.Action<T>' has some invalid arguments
Run Code Online (Sandbox Code Playgroud)
请注意,这不是您所说的异常,而是编译时错误CS1594的"即时窗口版本" .
另外,这样的通话将失败同样在编译的时候,因为没有来自隐性或显性的转换double来T.
这是debatably立即窗口的缺点(它似乎并不愿意使用额外的"运行时的知识",以帮助你在这种情况下),但人们可以说,它是合理的行为,因为等效呼叫制成在编译时(源代码中)也是非法的.这似乎是一个角落的情况; 即时窗口完全能够分配通用变量并执行在编译时非法的其他代码.也许罗斯林会使事情更加一致.
如果你愿意,你可以像这样解决这个问题:
genericDel.DynamicInvoke(42D);
Run Code Online (Sandbox Code Playgroud)
(要么)
((Action<double>)(object)genericDel)(42D);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1322 次 |
| 最近记录: |