24

私はPredicateBuilderジョセフ・アルバハリが書いた拡張メソッドを理解しており、これを見ましたがExpression.Invoke、正直なところ、次のメソッドでその理由を理解できませんでした:

public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> 
       expr1, Expression<Func<T, bool>> expr2)
{
  var invokedExpr = Expression.Invoke (expr2, 
      expr1.Parameters.Cast<Expression> ());

  return Expression.Lambda<Func<T, bool>> 
       (Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters);
}

彼はそれを少し説明しましたが:

興味深い作業は、And および Or メソッド内で行われます。最初の式のパラメーターを使用して 2 番目の式を呼び出すことから始めます。Invoke 式は、指定された式を引数として使用して、別のラムダ式を呼び出します。最初の式の本体と 2 番目の式の呼び出しバージョンから条件式を作成できます。最後のステップは、これを新しいラムダ式でラップすることです。

MSDNは次のように伝えています。

デリゲートまたはラムダ式を引数式のリストに適用する InvocationExpression を作成します。

これは私には少し理にかなっています。したがって、そのような式を使用する場合、基本的に引数を渡す必要はありません。

しかし、なぜかよく理解できませんでした。疲れたのか何かなのかな。

質問:

  1. いつ、どの状況で を使用するのが理にかなっていますかInvocationExpression
  2. Or<T>メソッド (またはAndElse<T>) メソッドがどのように機能するかを説明できる人はいますか?

アップデート:

InvocationExpression仕事から家に帰るときのことを考えていたとき、次のように頭に浮かびました。

メソッドを呼び出すとき、簡単に言うCallMe(phoneNumber, time);と、これはメソッド呼び出しと呼ばれます。そして、InvocationExpressionは を表す式である必要がありますCallMe(phoneNumber, time);LambdaExpressionなどのラムダを表現するのと似ていt => t + 2ます。したがって、基本的には、(パラメーターではなく) 引数に適用されるメソッド呼び出しです。そのため、呼び出しとして、パラメーターは必要なくなりましたが、引数が既にパラメーターに適用されているため、何かを返す可能性があります。

私が話しているコードの詳細については、http://www.albahari.com/nutshell/predicatebuilder.aspxをご覧ください。

4

1 に答える 1

42

式ではなく、デリゲートを使用していると想像してください。次に、次のように書くことができますOr

public static Func<T, bool> Or<T>(this Func<T, bool> expr1, Func<T, bool> expr2)
{
    return x => expr1(x) || expr2(x);
}

を使用して結合された 2 つのデリゲートを呼び出す新しいデリゲートを作成します||。これを式を使用するように書き換えると、デリゲートの呼び出しは次のようになりますExpression.Invoke()

public static Expression<Func<T, bool>> Or<T>(
    this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
    var parameter = Expression.Parameter(typeof(T), "x");
    var invokedExpr1 = Expression.Invoke(expr1, parameter);
    var invokedExpr2 = Expression.Invoke(expr2, parameter);

    return Expression.Lambda<Func<T, bool>>(
        Expression.OrElse(invokedExpr1, invokedExpr2), parameter);
}

実際の式がこのように書かれていない理由は、Or(ほとんどの場合) 最適化です。両方の式を呼び出す必要はなく、いずれかの本体とパラメーターを再利用できます。(ただし、パラメータが異なるため、両方を再利用することはできません。)

于 2013-11-09T00:47:15.280 に答える