1

単一のパラメーターを使用して、コンパイルされた Func(of boolean) と Expression(of Func(of boolean)) の両方を取得したいと思います。式ツリーを変更するつもりはありません。式ツリーを取得する唯一の理由は、実行中のコードを出力できるようにするためです。

void Assert(Expression<Func<bool>> assertionExpression) {
    if (!assertionExpression.Compile()()) 
    { 
        throw new AssertFailedException(assertionExpression.ToString()); 
    }
}

これを行う合理的な方法はありますか?

当然のことながら、単純なコンパイラで生成された式ツリーの場合、同じインスタンスが常にパラメーターとして渡されますか?

static Dictionary<Expression<Func<bool>>, Func<bool>> cache;

static void Assert(Expression<Func<bool>> assertionExpression) {
    Func<bool> method = null;
    if (!cache.TryGetValue(assertionExpression, out method)) {
        cache.Add(assertionExpression, method = assertionExpression.Compile());
        Console.WriteLine("cache insert");
    }
    else {
         Console.WriteLine("cache hit");
    }
    if (!method()) 
    { 
        throw new AssertFailedException(assertionExpression.ToString()); 
    }
}

static void someCodeThatExecutesRegularly() {
    Assert(()=>true);
}

public static void Main(string[] args, int argc) 
{
    someCodeThatExecutesRegularly();

    someCodeThatExecutesRegularly();

    someCodeThatExecutesRegularly();
}

出力は、「キャッシュ挿入」、「キャッシュ ヒット」、「キャッシュ ヒット」、または「キャッシュ挿入」、「キャッシュ挿入」、「キャッシュ挿入」になります。

4

1 に答える 1

1

最初の質問については、式ツリーを取得してコンパイルし、実行可能なバージョンを取得できますが、毎回再コンパイルするため、キャッシュする必要があります。

static void Assert(Expression<Func<bool>> assertionExpression) {
    var func = assertionExpression.Compile(); // if you call func() it will execute the expression
}

2番目の質問については、毎回新しい式ツリーになるため、「キャッシュ挿入」「キャッシュ挿入」「キャッシュ挿入」などを取得します...

キャッシュとコンパイルで動作させるには、式で .ToString() を使用して関数の文字列表現を取得できますが、文字列表現が同じである可能性があるため、クロージャーがある場合、これにより非常に混乱する問題が発生する可能性がありますが、閉じた変数は異なるため、これを行う場合は注意して使用してください。

于 2012-05-24T17:32:39.543 に答える