How to turn these 3 methods into one using C# gene

2020-06-18 07:57发布

问题:

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!

回答1:

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.



回答2:

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.



标签: c# generics