11

パラメータを使用してラムダ式を定義したいと考えていoutます。それは可能ですか?

以下は、私が試した C# .Net 4.0 コンソール アプリのコード スニペットです。

手順 25 でわかるように、ラムダ式を使用して出力パラメーターを持つデリゲートを定義できますが、linq 式を使用して同じことを行う場合、手順 24 のコードは次のように失敗します。

System.ArgumentException は処理されませんでしたメッセージ = タイプ 'System.Boolean' の ParameterExpression は、タイプ 'System.Boolean&' のデリゲート パラメーターには使用できませんソース = 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 の提案に基づいて動作するコード スニペットを次に示します。

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

}
4

1 に答える 1

8

必要なものType.MakeByRefType:

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

コード サンプルには追加の問題があることに注意してください。式本体が正しくありませんint。デリゲート型の戻り値の型を満たすために値を返す必要があるときに、値を返していません。

これを修正する方法は次のとおりです(ラムダの例のように):

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

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

outまた、式内でパラメーターを割り当てていないことにも注意してください。Expression.Lambdaこれは予想外でしたが、BCL は C# と同じルールに従う必要はありません。

于 2012-09-07T17:28:02.513 に答える