HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

Am I coding Java in C#?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
codingjavastackoverflow

Problem

Note: This ended up being much longer than I was expecting. I have a number of side questions that relate to specific parts of the code for if you don't want to slog through all this mess.

Background

I have had some experience in Java, but recently decided to learn C#. I would like to know if my first program is idiomatic.

I got the idea for this program out of a Java textbook I had lying around. Here's what it says:


Write a program that evaluates expressions typed in by the user. The
expressions can use real numbers, variables, arithmetic operators,
parentheses, and standard functions (sin, cos, tan, abs, sqrt, and log.)
A line of input must contain exactly one such expression. If extra
data is found on a line after an expression has been read, it is
considered an error. A variable name must consist of letters. Names
are case-sensitive. The program should accept commands of two types
from the user. For a command of the form print , the
expression is evaluated and the value is output. For a command of the
form let = , the expression is evaluated and
the value is assigned to the variable. If a variable is used in an
expression before it has been assigned a value, an error occurs.

I learned about using text mode in C#, so I went a little crazy with it.

Structure

My program is probably over 1000 lines long, so I'm not going to post the whole thing. Here's the basic breakdown of all the classes:

  • BraceMatcher.cs Contains a class that validates that the braces in an expression match.



  • CommandHandler.cs Contains a class that handles the commands sent from the user. A private nested inner exception class called MalformedAssignmentException deals with variable assignment commands that are malformed.



  • ConsoleFormatter.cs Contains a class that formats the Console IO for text mode.



  • IExpression.cs Contains an interface that represents a mathematical expression. The only method it defines is double Evaluate().



  • TermExpression.cs

Solution

First off, for somebody who is just learning C# you use it better than some of the people I work with.

Now to answer your questions:

-
You are correct, there is no native way to read numbers from the Console in C#. You could look at decimal.TryParse which tries parsing the input.

The code would look something like this:

var input = Console.ReadLine();

var inputAsNumber = 0d;
if (!decimal.TryParse(input, out inputAsNumber)
{
    // throw favorite exception
}


-
There is nothing wrong with default parameters. I like them better than having multiple constructors. I too think it's much cleaner.

-
There is nothing wrong with an IsEmpty method. C# has one for strings string.IsNullOrEmpty(string)

-
Using delegates this way is perfectly acceptable. I would look into Action and Action though. I think they are a little more common.

-
Your exception handling could be improved. You can catch multiple exceptions from one call:

try
{
    numBadCommands = 0;
    var name = ReadVariableName();
    ReadAssignmentOperator();

    var value = expressionReader.Read().Evaluate();

    expressionReader.StoreVariable(name, value);

    formatter.WriteOutput(
       String.Format("{0} set to {1}", name, value));
}
catch (MalformedAssignmentException ex)
{
    throw;
}
catch (InvalidExpressionException ex)
{
    throw;
}
catch (Exception ex)
{
    if (Console.In.Peek() != -1) 
    {
        Console.ReadLine();
    }
         formatter.WriteOutput(ex.Message);
}

Code Snippets

var input = Console.ReadLine();

var inputAsNumber = 0d;
if (!decimal.TryParse(input, out inputAsNumber)
{
    // throw favorite exception
}
try
{
    numBadCommands = 0;
    var name = ReadVariableName();
    ReadAssignmentOperator();

    var value = expressionReader.Read().Evaluate();

    expressionReader.StoreVariable(name, value);

    formatter.WriteOutput(
       String.Format("{0} set to {1}", name, value));
}
catch (MalformedAssignmentException ex)
{
    throw;
}
catch (InvalidExpressionException ex)
{
    throw;
}
catch (Exception ex)
{
    if (Console.In.Peek() != -1) 
    {
        Console.ReadLine();
    }
         formatter.WriteOutput(ex.Message);
}

Context

StackExchange Code Review Q#23900, answer score: 13

Revisions (0)

No revisions yet.