2012-09-07 26 views
10

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

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

あなたは、私が同じことを行うためにLINQの式を使用したい場合、私は、しかし、出力パラメータを持つデリゲートを定義するには、ラムダ式を使用することができますProcedure25で見ることができるように、手順24でコードがで失敗します

System.ArgumentExceptionのは、私が使用することができます知っている= System.Core

「可能System.Boolean &」ソース「可能System.Boolean」タイプの未処理メッセージ= ParameterExpression たタイプ のデリゲートパラメータのために使用することはできません入力クラスobjそのような方法で呼び出し元に値を渡しますが、何らかの形でパラメータを定義できるかどうか不思議でした。

おかげ

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

EDIT:

阿仁、素晴らしい、ありがとう。したがって、重要なことは、パラメータタイプでMakeByRefTypeを呼び出すことでした。ここでの記録のために

はアニの提案に基づいて動作するコードスニペットです:

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

} 

答えて

7

あなたはType.MakeByRefTypeを必要とする:あなたのコードサンプルは、付加的な問題があることを

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

注:お使いのexpression- bodyが正しくありません。intを返して、デリゲート型の戻り値の型を満たす必要があるときに値を返していません。ここで

は、あなたが(あなたのラムダの例のように)それを修正することができます方法です。

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

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

はまた、あなたが式の中outパラメータを割り当てていないことに注意してください。 Expression.Lambdaは、私が期待していなかったものを手に入れようとしていますが、BCLはC#と同じ規則に従う必要はありません!

関連する問題