Was ist die Motivation für die Implementierung von C # ExpressionVisitor?

8

Ich muss eine Lösung für eine Aufgabe entwerfen, und ich möchte etwas verwenden, das C # 's ExpressionVisitor theoretisch ähnlich ist.

Aus Neugierde habe ich die .NET-Quellen für ExpressionVisitor geöffnet, um einen Blick darauf zu werfen. Seit dieser Zeit frage ich mich, warum das .NET-Team den Besucher so implementiert hat wie sie.

Zum Beispiel sieht MemberInitExpression.Accept folgendermaßen aus:

%Vor%

Meine - wahrscheinlich noob - Frage ist: macht es irgendeinen Sinn? Ich meine, sollte nicht die Accept-Methode selbst dafür verantwortlich sein, wie sie den Besuch in sich selbst umsetzt? Ich meine, ich habe so etwas erwartet (die internal Sichtbarkeit kann von außen nicht überschrieben werden):

%Vor%

Aber dieser Code ist in der Methode ExpressionVisitor von VisitMemberInit , die von MemberInitExpression.Accept aufgerufen wird. Es scheint also keinen Vorteil der Accept Umsetzung hier zu geben.

Warum verarbeiten Sie nicht einfach den Baum in der Basis ExpressionVisitor und vergessen Sie alle Accept Methoden?

Ich hoffe, Sie verstehen meine Punkte und hoffen, dass jemand die Motivation hinter dieser Umsetzung beleuchten könnte. Vermutlich verstehe ich das Besuchermuster überhaupt nicht? ...

    
Zoltán Tamási 22.01.2015, 14:41
quelle

2 Antworten

2

Ein Besucher kann die Art und Weise, wie ein Ausdruck besucht wird, überschreiben. Wenn Ihr Vorschlag an allen Orten implementiert wurde, würde der Besucher nie aufgerufen werden. Die gesamte Besuchslogik wäre in den Überschreibungen von Accept enthalten. Nicht-BCL-Code kann diese Methode nicht überschreiben.

Wenn Sie visitor.Visit((Expression)this.SomeExpression) schreiben (wie Sie es in der Frage tun), wie werden Sie den dynamischen Versand für den Typ SomeExpression durchführen? Jetzt muss der Besucher den dynamischen Versand durchführen. Beachten Sie, dass Ihr zweites Code-Snippet die vereinfachende Annahme macht, dass alle zu durchsuchenden Unter-Ausdrücke einen bekannten Typ haben. Versuchen Sie, den Code für BinaryExpression zu schreiben, um zu sehen, was ich meine.

Vielleicht habe ich etwas nicht verstanden, aber dieser Vorschlag macht keinen Sinn.

Der Zweck der Methode Accept ist eine Leistungsoptimierung. Jedes Akzeptieren ist ein virtueller Anruf, der ziemlich billig ist. Die Alternative wäre, einen großen Schalter im Besucher über den Ausdruckstyp zu haben (der eine Aufzählung ist). Das ist wahrscheinlich langsamer.

    
usr 22.01.2015, 14:57
quelle
2

Das Besuchermuster erlaubt es, den Algorithmus im Wesentlichen von der Struktur zu trennen, auf der er arbeitet. In diesem Fall ist die Struktur, auf der es operiert, der Ausdrucksbaum.

Beachten Sie, dass die Methode Accept im Besucher virtual ist. Dies bedeutet, dass wir möglicherweise verschiedene Implementierungen von ExpressionVisitor schreiben könnten, die verschiedene Dinge in einem Ausdrucksbaum machen (und tatsächlich gibt es verschiedene Implementierungen). Und wir können dies tun, ohne irgendeinen Code in den Ausdrucksbaum-Klassen selbst zu ändern.

Beispiele für verschiedene Besucherimplementierungen können etwa so aussehen, als hätten Sie einen Besucher, der den Ausdrucksbaum wieder in eine Zeichenfolge verwandelt, die C # -Code (oder vielleicht Code in einer anderen Sprache) darstellt.

    
Kyle 22.01.2015 15:05
quelle