3

I am testing polymorphism in C# with generic types and trying to find the way to make generics countable but C# compiler does not accept operation such as summation on generic types. I found one of the workarounds based on which I created the code below that inherits from an interface that provides a proper function:

using System.IO;
using System;

interface ICountable<T>
{
    T Add(T a, T b);
    T Multiply(T a, T b);
}

interface IExecute<T> : ICountable<T>
{
    T Operation(T a, T b);
}

class IntSum : IExecute<int>
{
    public int Add(int a, int b)
    {
        return a + b;
    }
    public int Multiply(int a, int b)
    {
        return a*b;
    }
    public int Operation(int a, int b)
    {
        return Add(a,b);
    }
}
class DoubleMultiply : IExecute<double>
{
    public double Add(double a, double b)
    {
        return a + b;
    }
    public double Multiply(double a, double b)
    {
        return a*b;
    }
    public double Operation(double a, double b)
    {
        return Multiply(a,b);
    }
}

class Program
{
    static void Main()
    {
        Console.WriteLine(DoOperation(new IntSum(), 1, 2));
        Console.WriteLine(DoOperation(new DoubleMultiply(), 3.5d, 3d));
    }

    static TResult DoOperation<TOperand, TResult>(TOperand obj, TResult a, TResult b)
    where TOperand : IExecute<TResult>
    {
        return obj.Operation(a,b);
    }
}

The code above works but in the end I use inheriting to a concrete primitive types and there's a lot of redundant code blocks. My ultimate goal would be to make such types as much generic as possible, something similar to this:

using System.IO;
using System;

interface ICountable<T>
{
    T Add(T a, T b);
    T Multiply(T a, T b);
}

interface IExecute<T> : ICountable<T>
{
    T Operation(T a, T b);
}

// Generic code
class Sum<T> : IExecute<T>, ICountable<T>
{
    public T Add(T a, T b)
    {
        return a + b;
    }
    public T Multiply(T a, T b)
    {
        return a*b;
    }
    public T Operation(T a, T b)
    {
        return Add(a,b);
    }
}

class Program
{
    static void Main()
    {
        //Console.WriteLine(DoOperation(new IntSum(), 1, 2));
        //Console.WriteLine(DoOperation(new DoubleMultiply(), 3.5d, 3d));
    }

    //static TResult DoOperation<TOperand, TResult>(TOperand obj, TResult a, TResult b)
    //where TOperand : IExecute<TResult>
    //{
    //    return obj.Operation(a,b);
    //}
}

Obviously, the compiler complains as it cannot sum two generic types. Do you think I always have to inherit to specific primitive? Thanks.

Celdor
  • 2,437
  • 2
  • 23
  • 44
  • 2
    How about [operator overloading](https://msdn.microsoft.com/en-us/library/aa288467(v=vs.71).aspx)? Maybe combined with [constraints on the type parameter](https://msdn.microsoft.com/en-us/library/d5x73970.aspx)? – KeyNone Aug 18 '15 at 12:51
  • You could check T's type, so at least you only have the one class Sum – Andy Wiesendanger Aug 18 '15 at 12:56
  • 1
    @BastiM You cannot overload operators for generics. I also tried to apply constraints `struct` for primitive types. – Celdor Aug 18 '15 at 13:01
  • You can't overload them directly, but [it's working quite well!](http://ideone.com/xbuutR) – KeyNone Aug 18 '15 at 13:16
  • If you want to do this in a type-safe way (without reflection/dynamic) then your only option is to implement it for every type you care about explicitly. There is no way to abstract across overloaded methods using generics. – Lee Aug 18 '15 at 13:21
  • if this question is a duplicate, can I please see the link to original question? – Celdor Aug 18 '15 at 13:39

1 Answers1

0

You can use Expression.Add() and Expression.Multiply() to achieve this. Note that they will throw an exception if the addition/multiplication operator is not defined for the type you use.

Dave C
  • 211
  • 4
  • 6