【问题标题】:Is it possible to have an out ParameterExpression?是否有可能有一个输出参数表达式?
【发布时间】:2012-09-01 14:31:17
【问题描述】:

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

以下是我尝试过的 C# .Net 4.0 控制台应用程序中的代码 sn-ps。

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

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

我知道我可以使用带有 bool 成员的输入类对象并以这种方式将值传回给调用者,但我很好奇是否可以以某种方式定义出参数。

谢谢

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);
}

编辑:

阿尼,太棒了,谢谢。所以关键是在参数类型上调用 MakeByRefType。

为了记录,这里是一个基于 Ani 建议的代码 sn-p:

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);

}

【问题讨论】:

    标签: c# .net linq .net-4.0 expression-trees


    【解决方案1】:

    你需要Type.MakeByRefType:

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

    请注意,您的代码示例还有一个问题:您的表达式主体不正确 - 当它应该返回 int 以满足委托类型的返回类型时,它没有返回值。

    您可以通过以下方式解决该问题(例如您的 lambda 示例):

    var body = Expression.Block(methodCall, Expression.Constant(1));
    
    Expression.Lambda<Evaluate>(body, valueParameter, usesVarsParameter)
              .Compile()("test", out usesVars);
    

    另请注意,您没有在表达式中分配 out 参数。 Expression.Lambda 让你侥幸逃脱,这是我没想到的,但是,嘿,BCL 不必遵循与 C# 相同的规则!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-23
      • 1970-01-01
      • 2014-08-30
      • 2021-08-30
      • 2023-01-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多