Que fait Expression.Reduce ()?

.net c# expression-trees lambda

Question

Je travaille avec des arbres d'expression depuis quelques jours maintenant et je suis curieux de savoir ce que fait Expression.Reduce (). La documentation de msdn n’est pas très utile car elle indique seulement qu’elle "réduit" l’expression. Juste au cas où, j’ai essayé un exemple (voir ci-dessous) pour vérifier si cette méthode comprenait une réduction mathématique, mais cela ne semble pas être le cas.

Est-ce que quelqu'un sait ce que fait cette méthode et est-il possible de donner un exemple rapide montrant qu'elle est en action? De bonnes ressources là-bas?

static void Main(string[] args)
{
    Expression<Func<double, double>> func = x => (x + x + x) + Math.Exp(x + x + x);
    Console.WriteLine(func);
    Expression r_func = func.Reduce();
    Console.WriteLine(r_func); // This prints out the same as Console.WriteLine(func)
}

Réponse acceptée

Le document à examiner est "expr-tree-spec.doc" ici: http://dlr.codeplex.com/wikipage?title=Docs%20and%20specs&referringTitle=Documentation

Ceci est la spécification pour les arbres d'expression. Lisez les sections "2.2 Nodes réductibles" et "4.3.5 Méthode de réduction".

Fondamentalement, cette méthode est destinée aux personnes qui implémentent ou portent leur langage dynamique vers .NET. Ils peuvent ainsi créer leurs propres nœuds pouvant être réduits à des nœuds d'arborescence d'expression standard et pouvant être compilés. Il y a quelques nœuds "réductibles" dans l'API des arbres d'expression, mais je ne sais pas si vous pouvez obtenir des exemples pratiques (puisque tous les nœuds d'expression standard se compilent de toute façon, en tant qu'utilisateur final, vous ne vous souciez probablement pas de savoir s'ils sont "réduits" "dans les coulisses ou non).

Oui, la documentation MSDN est très basique dans ce domaine, car la principale source d'informations et de documents pour les développeurs de langage est http://dlr.codeplex.com/


Réponse populaire

Avec un peu de désassemblage, je trouve que Expression.CanReduce reutrns toujours false et Expression.Reduce () retourne toujours this . Cependant, il existe quelques types qui remplacent les deux. LambdaExpression hérite des implémentations par défaut, ce qui explique pourquoi les expressions essayées jusqu'à présent ne fonctionnent pas.

MemberInitExpression est l'un des types qui redéfinit Réduction (), ce qui m'a conduit à l'expérience réussie suivante:

class ReduceFinder : ExpressionVisitor {
    public override Expression Visit(Expression node) {
        if (node != null && node.CanReduce) {
            var reduced = node.Reduce();
            Console.WriteLine("Found expression to reduce!");
            Console.WriteLine("Before: {0}: {1}", node.GetType().Name, node);
            Console.WriteLine("After: {0}: {1}", reduced.GetType().Name, reduced);
        }
        return base.Visit(node);
    }
}

class Foo {
    public int x;
    public int y;
}

static class Program {
    static void Main() {
        Expression<Func<int, Foo>> expr = z => new Foo { x = (z + 1), y = (z + 1) };
        new ReduceFinder().Visit(expr);
    }
}

Sortie:

Found expression to reduce!  
Before: MemberInitExpression: new Foo() {x = (z + 1), y = (z + 1)}  
After: ScopeN: { ... }  


Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi