是否可以使用out ParameterExpression? [英] Is it possible to have an out ParameterExpression?

查看:80
本文介绍了是否可以使用out ParameterExpression?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用out参数定义一个Lambda表达式.有可能做到吗?

I want to define a Lambda Expression with an out parameter. Is it possible to do it?

下面是我尝试过的C#.Net 4.0控制台应用程序中的代码段.

Below are code snippets from a C# .Net 4.0 console app that I tried.

正如在Procedure25中所看到的,我可以使用lambda表达式来定义具有输出参数的委托,但是,当我想使用linq表达式执行相同的操作时,过程24中的代码将失败,并显示以下信息:

As you can see in Procedure25 I can use lambda expressions to define a delegate that has an output parameter, however, when I want to use linq expressions to do the same, the code in procedure 24 fails with:

System.ArgumentException未处理Message = ParameterExpression 类型'System.Boolean'的类型不能用于类型的委托参数 "System.Boolean&" Source = System.Core

System.ArgumentException was unhandled Message=ParameterExpression of type 'System.Boolean' cannot be used for delegate parameter of type 'System.Boolean&' Source=System.Core

我知道我可以使用带有bool成员的输入类对象,然后以这种方式将值传递回调用方,但是我很好奇是否可以通过某种方式定义参数.

I know I could use an input class object with a bool member and pass back the value to the caller that way but I was curious if I could somehow define out parameters.

谢谢

static void Main(string[] args)
{
  Procedure25();
  Procedure24();
  Console.WriteLine("Done!");
  Console.ReadKey();
}

private delegate int Evaluate(string value, out bool usesVars);

private static void Procedure24()
{

  // This fails to compile:
  //Expression<Evaluate> x = (string val,  out bool usesSimVals) =>
  //{
  //  usesSimVals = true;
  //  Console.WriteLine(val);
  //  return 1;
  //};


  ParameterExpression valueParameter = Expression.Parameter(typeof (string));
  MethodCallExpression methodCall = Expression.Call(typeof(Console).GetMethod("WriteLine", new Type[] { typeof(object) }), valueParameter);

  bool usesVars;
  ParameterExpression usesVarsParameter = Expression.Parameter(typeof (bool), "out usesVars");


  Expression.Lambda<Evaluate>(methodCall, valueParameter, usesVarsParameter).Compile()("test", out usesVars);
  Console.WriteLine(usesVars);

}

private static void Procedure25()
{
  Evaluate x = (string value, out bool vars) => { vars = true;
    Console.WriteLine(value);
                                                    return 1;
  };

  bool usesVars;
  x("test", out usesVars);
}

Ani,太好了,谢谢.所以关键是要在参数类型上调用MakeByRefType.

Ani, awesome, thanks. So the key thing was to call MakeByRefType on the parameter type.

为便于记录,以下是根据Ani的建议工作的代码段:

For the record here is a code snippet that works based on Ani's suggestion:

private static void Procedure24()
{
  ParameterExpression valueParameter = Expression.Parameter(typeof (string));
  MethodCallExpression methodCall = Expression.Call(typeof(Console).GetMethod("WriteLine", new Type[] { typeof(object) }), valueParameter);

  bool usesVars;
  ParameterExpression usesVarsParameter = Expression.Parameter(typeof (bool).MakeByRefType(), "out usesVars");

  Expression block = Expression.Block(methodCall, Expression.Assign(usesVarsParameter, Expression.Constant(true)), Expression.Constant(1));
  int result = Expression.Lambda<Evaluate>(block, valueParameter, usesVarsParameter).Compile()("test", out usesVars);
  Console.WriteLine("Result={0}, usesVars={1}", result, usesVars);

}

推荐答案

您需要 Type.MakeByRefType :

var usesVarsParameter = Expression.Parameter(typeof(bool).MakeByRefType(), "usesVars");

请注意,您的代码示例还有另一个问题:您的expression-body不正确-当它应该返回int以满足委托类型的return-type时,它没有返回值.

Note that your code sample has an additional problem: your expression-body isn't correct - it's not returning a value when it should be returning an int to satisfy the delegate-type's return-type.

这是一种可以解决此问题的方法(例如您的lambda示例):

Here's a way you can fix that (like your lambda example):

var body = Expression.Block(methodCall, Expression.Constant(1));

Expression.Lambda<Evaluate>(body, valueParameter, usesVarsParameter)
          .Compile()("test", out usesVars);

还请注意,您没有在表达式内分配out参数. Expression.Lambda让您摆脱它,这没想到,但是,嘿,BCL不必遵循与C#相同的规则!

Also note that you are not assigning the out parameter inside the expression. Expression.Lambda is letting you get away with it, which I didn't expect, but hey, the BCL doesn't have to follow the same rules as C#!

这篇关于是否可以使用out ParameterExpression?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆