Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to turn these 3 methods into one using C# generics?

Tags:

c#

generics

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!

like image 555
Phil Wright Avatar asked Oct 05 '08 08:10

Phil Wright


2 Answers

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.

like image 89
Marc Gravell Avatar answered Sep 30 '22 06:09

Marc Gravell


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.

like image 45
Jon Skeet Avatar answered Oct 03 '22 06:10

Jon Skeet