C# - operator overloading through inheritance

61 views Asked by At

I am trying to come up with the way to implement a way to perform a Mutation test on my class (yes I am aware of Stryker .NET).

For the sake of simplicity, let's say that I want to write a Mutator class that some service will inherit from, and it will convert all additions to subtraction. I am wondering whether it is possible to achieve this without doing any changes to the service class.

I have this service that performs a simple addition

public class Service : Mutator
{

    public int AddTwoNumbers(int firstNum, int secondNum)
    {
        return firstNum + secondNum;
    }
}

at first, I simply tried to write Mutator class as follows:

 public class Mutator
 {
     public static int operator +(int a, int b)
     {
         return a - b;
     }
 }

but of course quickly discovered that following code produces compiler error ("One of the parameters of a binary operator must be the containing type")

So I wonder, if there is a way to achieve this kind of mutation trough inheritance without changing the actual Service class.

The reason I choose operator overloading instead of method overloading or something like that is because I want to be able to inherit from this Mutator from any random class and to just simply change all + into -

1

There are 1 answers

2
ThatGuy On

It tells you that one of the operator params need to be the type of the overloading class itself. The operator+ overload must have a param of type Mutator.

What you want to do is inherently impossible for all types because:

  1. Any type could implement subtraction however they want,
  2. There are no guarantees that the + and - operators were overloaded by a type in the first place, and
  3. Operator overloads must have a parameter that matches the type overloading them.

However, it is possible to achieve this to some degree. You can implement Mutator to be generic and add constraints to it so you know that a derived type will have an addition or subtraction that you can swap. You will not be able to use generic T as params alone, though. Mutator will have to be a wrapper class. Here is an example:

public static void Main()
{
    var origin = new Mutator<long>(10L);
    var x = origin + 3; // 7
    var y = origin - 3; // 13

    Console.WriteLine($"origin: {origin.Value}");
    Console.WriteLine($"x: {x}");
    Console.WriteLine($"y: {y}");
}

class Mutator<T>(T value)
    where T : IAdditionOperators<T, T, T>, ISubtractionOperators<T, T, T>
{
    public T Value { get; set; } = value;

    public static T operator +(Mutator<T> x, T y)
        => x.Value - y;

    public static T operator -(Mutator<T> x, T y)
        => x.Value + y;
}