tags:

views:

566

answers:

2

I have not used generics much and so cannot figure out if it is possible to turn the following three methods into one using generics to reduce duplication. Actually my code currently has six methods but if you can solve it for the three then the rest should just work anyway with the same solution.

    private object EvaluateUInt64(UInt64 x, UInt64 y)
    {
        switch (Operation)
        {
            case BinaryOp.Add:
                return x + y;
            case BinaryOp.Subtract:
                return x - y;
            case BinaryOp.Multiply:
                return x * y;
            case BinaryOp.Divide:
                return x / y;
            case BinaryOp.Remainder:
                return x % y;
            default:
                throw new ApplicationException("error");
        }
    }

    private object EvaluateFloat(float x, float y)
    {
        switch(Operation)
        {
            case BinaryOp.Add:
                return x + y;
            case BinaryOp.Subtract:
                return x - y;
            case BinaryOp.Multiply:
                return x * y;
            case BinaryOp.Divide:
                return x / y;
            case BinaryOp.Remainder:
                return x % y;
            default:
                throw new ApplicationException("error");
        }
    }

    private object EvaluateDouble(double x, double y)
    {
        switch (Operation)
        {
            case BinaryOp.Add:
                return x + y;
            case BinaryOp.Subtract:
                return x - y;
            case BinaryOp.Multiply:
                return x * y;
            case BinaryOp.Divide:
                return x / y;
            case BinaryOp.Remainder:
                return x % y;
            default:
                throw new ApplicationException("error");
        }
    }

I am building a simple expression parser that then needs to evaluate the simple binary operations such as addition/subtraction etc. I use the above methods to get the actual maths performed using the relevant types. But there has got to be a better answer!

+9  A: 

Generics doesn't natively support arithmetic. However, it can be done with .NET 3.5, like so. The Operator class is part of MiscUtil. This then becomes:

   public T Evaluate<T>(T x, T y) {
      switch (Operation)
      {
        case BinaryOp.Add:
            return Operator.Add(x, y);
        case BinaryOp.Subtract:
            return Operator.Subtract(x, y);
     ... etc

Since you are writing an expression parser, it might be a good idea to use Expression directly, but you're welcome to use the above.

Marc Gravell
Contrary to popular speculation, Marc and I are actually two separate people. We just seem to occasionally share a mind.
Jon Skeet
Maybe we just *think* that... ever see Fight Club?
Marc Gravell
Exchangable brains? Cool.
EricSchaefer
@Eric: I think it uses dependency injection - I'm just worried that I have the Rhino mock, and Jon has the production version...
Marc Gravell
That's really really cool. I still think MS should have added operator support to generics though :-(
Orion Edwards
+4  A: 

Marc Gravell has done a lot of work on making generic maths viable. See the MiscUtil and general article about the issue.

The code in the current version of MiscUtil requires .NET 3.5 due to its use of expression trees. However, I believe Marc has a version which works with .NET 2.0 as well. If this would be useful to people, I'm sure we could incorporate it somehow (possibly with a facade in MiscUtil itself which would use the appropriate implementation based on framework version at runtime).

For the future, I'd like to see static interfaces which could provide an alternative way of working with generic maths types.

Jon Skeet
I'd probably need to re-do the 2.0 - I think it died on a HDD; I e-mailed you a copy once - don't suppose you still have it? It isn't a huge amount of work, though...
Marc Gravell
I quite possibly have it. Can't check now, but will look later if you remind me.
Jon Skeet