Pergunta

Let's say I have an abstract Node class and BinaryOperation class derived from Node and three classes IntegerConstant, RealConstant and CharacterConstant also derived from Node.

The general design for the BinaryOperation class would look like this:

public class BinaryOperation : Node
{
    public Node Operand1 { get; private set; }
    public Node Operand2 { get; private set; }
    //...
}

I also have parsing methods for those classes, each of them returning given type. So IsIntegerConstant() is of type IntegerConstant and so on.

Now when parsing an operand in expression I could easily check the type like this:

Node operand1 = IsIntegerConstant() ??
                IsRealConstant() ??
                IsCharacterConstant();

However C# does not allow that. Because compiler cannot determine the type of the expression in operand1 assignment. What should I do? Should I make all of the parsing methods return type Node or cast each method to Node. Or maybe create separate BinaryOperation class members for each of the operand types?

Foi útil?

Solução

What should I do? Should I make all of the parsing methods return type Node or cast each method to Node.

I'd suggest adding, to use here in your example, a more general operand-parsing wrapper that returns Node whose implementation internally determines the type of the operand perhaps using such cascading.

Or maybe create separate BinaryOperation class members for each of the operand types?

No, don't do that! This seems like class explosion to me. You'd need a subclass for each left operand subclass X a subclass for each right operand subclass — a whole matrix of classes, for what I can only see as little-to-no value.


What do you do if all including the last IsCharacterConstant() fails? It seems that operand1 becomes null in that case, ignoring the parse input — rather than getting some useful error. You might try:

Node operand1 = IsIntegerConstant() ??
                IsRealConstant() ??
                IsCharacterConstant() ??
                ReportError("... this operator must have a constant left operand ...");

where ReportError has declared return type of Node, thus satisfying the C# inference algorithm.


I'm not familiar with this parsing technique; it seems very specific, are you thinking it will support your long term needs? Do you not support parenthesis or nested binary operations?

I ask because the question of type inference ugliness becomes moot if a more general parsing method is needed anyway — as a more general method might parse an operand to a Node, making this cascading not so broadly visible across your code base, if not eliminating it.

Licenciado em: CC-BY-SA com atribuição
scroll top