Only a few hours left (part 4)
So we left off on the previous post with the question of why we were using Java to work with our new token visitors. Can't visitors be used in C# as well? Well, yes. However, not necessarily as conveniently as with Java. How so? Well, let's take a look at what the code would look like in C#. First off, the visitor interfaces and DefaultTokenVisitor will be the same as with the java code (albeit with slight syntactic differences). However, in order to write the parser we'd have to do the following:
public class Parser {
Token CurrentToken { get { ... } }
void parseType() {
parseModifiers();
CurrentToken.AcceptVisitor(new DetermineTypeToParse(this));
//Parse rest of type
}
void parseModifiers() { ... }
void parseClass() { ... }
void parseInterface() { ... }
class DetermineTypeToParse : DefaultTokenVisitor {
readonly Parser parser;
public DetermineTypeToParse(Parser parser) {
this.parser = parser;
}
public override void VisitClassToken(ClassToken token) {
parser.parseClass();
}
public override void VisitInterfaceToken(InterfaceToken token) {
parser.parseInterface();
}
/* include other cases */
public override void Default(Token token) {
/* handle error */
}
}
}
Functionally, this is equivalent to the java code above (and in actuality is basically what the java compiler is generating when you type in the anonymous inner class), however we've lost quite a lot in the translation. Specifically, we've now had to separate and make disjoint the parser's logic and the visitor's logic. However, both sets of logic are closely related and benefit highly from tight locality in the code. Depending on how the code is structured, and how many visitors are needed, you might end up having this logic hundreds of lines apart. Verifying then that the parser code works as it should is far too difficult, and unclear. You also end up creating a type that exists solely to be instantiated in one and only one location. But you've now cluttered your namespace with this class which you then need to police to ensure that it's used properly.
So while the visitor pattern is fully functional from C#, it lacks the usability that one would want in order to use it as a core designing principle in your APIs. Is there a way that we can get the power of visitors without this drawback? Wait and see!
Comments
- Anonymous
September 12, 2005
Since anonymous delegates are generally claimed to be the workaround for C#'s lack of anonymous inner classes one would hope that they can be used in this situation too. - Anonymous
September 13, 2005
They're actually called "anonymous methods" :) - Anonymous
September 13, 2005
msdn.microsoft.com has both terms in wide use. :p