c#表达式树中的ByRef参数
本文关键字:ByRef 参数 表达式 | 更新日期: 2023-09-27 18:17:44
如果我想创建一个表达式树,调用具有out
参数的方法,然后返回out
值作为结果。我该怎么做呢?
下面的代码不起作用(抛出运行时异常),但也许最好地演示了我要做的事情:
private delegate void MyDelegate(out int value);
private static Func<int> Wrap(MyDelegate dele)
{
MethodInfo fn = dele.Method;
ParameterExpression result = ParameterExpression.Variable(typeof(int));
BlockExpression block = BlockExpression.Block(
typeof(int), // block result
Expression.Call(fn, result), // hopefully result is coerced to a reference
result); // return the variable
return Expression.Lambda<Func<int>>(block).Compile();
}
private static void TestFunction(out int value)
{
value = 1;
}
private static void Test()
{
Debug.Assert(Wrap(TestFunction)() == 1);
}
我知道这可以在原始IL中相当容易地解决(或者实际上根本没有运行时编译),但不幸的是,这是一个更大的表达式构建过程的一部分…所以我真的希望这不是一个限制,因为完全重写会更痛苦。
这个适合我:
private static Func<int> Wrap(MyDelegate dele)
{
var fn = dele.Method;
var result = ParameterExpression.Variable(typeof(int));
var block = BlockExpression.Block(
typeof(int),
new[] { result },
new Expression[]
{
Expression.Call(fn, result),
result,
});
return Expression.Lambda<Func<int>>(block).Compile();
}
也许只有我这样,但我真的不明白整件事的意义。为了完成你想做的事情,你真的不需要把所有的东西都写下来。
控制台应用程序中的示例代码:
class Program
{
static void Main(string[] args)
{
var temp = Execute(DoSomething);
Console.Write(temp);
Console.Read();
}
static int Execute(Func<int> methodToRun)
{
return methodToRun.Invoke();
}
static int DoSomething()
{
return 1;
}
}
如您所见,它以更简洁和干净的方式获得相同的结果。我认为你错过的是Action
, Action<>
和Func<>
都是delegate
的单义糖,所以不需要混合两种语法,也不需要像你那样重构整个表达式。