Maison >développement back-end >C++ >Comment combiner deux objets d'expression à l'aide d'opérateurs logiques?

Comment combiner deux objets d'expression à l'aide d'opérateurs logiques?

Barbara Streisand
Barbara Streisandoriginal
2025-01-31 05:41:09354parcourir

Cet article explore les méthodes pour combiner deux objets Expression<Func<bool>> utilisant des opérateurs logiques en C #. Directement à l'aide de AND ou OR n'est pas possible; Au lieu de cela, Expression.AndAlso, OrElse et Not sont utilisés. La complexité augmente lorsque les expressions utilisent différents paramètres. Trois solutions sont présentées:

How to Combine Two Expression Objects Using Logical Operators?

combinant deux expressions booléennes

Le défi réside dans la combinaison de deux objets Expression<Func<bool>> utilisant logique et, ou, ou non. Une approche simple comme expr1 AND expr2 est invalide.

Solutions

Plusieurs méthodes abordent ceci:

Méthode 1: Utilisation de Invoke

Cette méthode utilise la méthode Invoke pour exécuter chaque expression dans un contexte de paramètre commun.

<code class="language-csharp">static Expression<Func<bool>> AndAlso<T>(
    this Expression<Func<bool>> left,
    Expression<Func<bool>> right)
{
    var param = Expression.Parameter(typeof(T), "x");
    var body = Expression.AndAlso(
            Expression.Invoke(left, param),
            Expression.Invoke(right, param)
        );
    var lambda = Expression.Lambda<Func<bool>>(body, param);
    return lambda;
}</code>

Méthode 2: remplacement des paramètres (conditionnel)

Cette approche vérifie si les expressions partagent le même paramètre. Si c'est le cas, un AndAlso plus simple est utilisé. Sinon, il invoque la deuxième expression en utilisant le paramètre du premier.

<code class="language-csharp">static Expression<Func<bool>> AndAlso<T>(
    this Expression<Func<bool>> expr1,
    Expression<Func<bool>> expr2)
{
    ParameterExpression param = expr1.Parameters[0];
    if (ReferenceEquals(param, expr2.Parameters[0]))
    {
        return Expression.Lambda<Func<bool>>(
            Expression.AndAlso(expr1.Body, expr2.Body), param);
    }
    return Expression.Lambda<Func<bool>>(
        Expression.AndAlso(
            expr1.Body,
            Expression.Invoke(expr2, param)), param);
}</code>

Méthode 3: ExpressionVisitor

Cette méthode sophistiquée utilise un ExpressionVisitor pour remplacer systématiquement les paramètres d'une expression pour correspondre à l'autre avant d'appliquer AndAlso.

<code class="language-csharp">public static Expression<Func<bool>> AndAlso<T>(
    this Expression<Func<bool>> expr1,
    Expression<Func<bool>> expr2)
{
    var parameter = Expression.Parameter(typeof(T));

    var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0], parameter);
    var left = leftVisitor.Visit(expr1.Body);

    var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter);
    var right = rightVisitor.Visit(expr2.Body);

    return Expression.Lambda<Func<bool>>(
        Expression.AndAlso(left, right), parameter);
}

private class ReplaceExpressionVisitor : ExpressionVisitor
{
    private readonly Expression _oldValue;
    private readonly Expression _newValue;

    public ReplaceExpressionVisitor(Expression oldValue, Expression newValue)
    {
        _oldValue = oldValue;
        _newValue = newValue;
    }

    public override Expression Visit(Expression node)
    {
        if (node == _oldValue)
            return _newValue;
        return base.Visit(node);
    }
}</code>

Le choix de la méthode dépend de la complexité de vos expressions et du besoin de performances optimisées. La méthode 1 est simple, la méthode 2 offre une amélioration des performances lorsque les paramètres correspondent, et la méthode 3 fournit une solution robuste pour gérer les paramètres disparates.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn