# F-bounded polymorphism, interface operators, and type inference in C#

C# language version 8.0 introduces limited support for static methods, operators, etc. in interfaces. However, there are still limitations. I was hoping to use the new language features to try a generic approach to abstract algebra with proper operator overloading, but I'm running into the limitations.

Ideally what I'd like is

```
public interface IRing<TRing> where TRing : IRing<TRing>
{
public static TRing operator -(TRing a);
public static TRing operator +(TRing a, TRing b);
public static TRing operator -(TRing a, TRing b) => a + -b;
public static TRing operator *(TRing a, TRing b);
}
```

which can be used as e.g.

```
static TRing EvaluatePolynomial<TRing>(TRing x, params TRing[] coeffsBE)
where TRing : IRing<TRing>
{
var y = x - x; // Initially zero
foreach (var coeff in coeffsBE)
y = y * x + coeff;
return y;
}
```

There are two obvious problems: static members of interfaces need implementations, and operator overloads must use the enclosing type. The first is easy enough to work around:

```
public interface IRing<TRing> where TRing : IRing<TRing>
{
TRing Negate();
TRing Add(TRing addend);
TRing Mul(TRing addend);
public static TRing operator -(TRing a) => a.Negate(b);
public static TRing operator +(TRing a, TRing b) => a.Add(b);
public static TRing operator -(TRing a, TRing b) => a + -b;
public static TRing operator *(TRing a, TRing b) => a.Mul(b);
}
```

But the second is problematic. If I try changing the type of the first argument of each operator overload to `IRing<TRing>`

:

```
public interface IRing<TRing> where TRing : IRing<TRing>
{
TRing Negate();
TRing Add(TRing addend);
TRing Mul(TRing multiplicand);
public static TRing operator -(IRing<TRing> a) => a.Negate();
public static TRing operator +(IRing<TRing> a, TRing b) => a.Add(b);
public static TRing operator -(IRing<TRing> a, TRing b) => a + -b;
public static TRing operator *(IRing<TRing> a, TRing b) => a.Mul(b);
}
```

then the generic `EvaluatePolynomial`

compiles, but operations on specific implementations don't necessarily. This simple implementation:

```
public struct BigInt : IRing<BigInt>
{
private BigInt(BigInteger value) { Value = value; }
public static implicit operator BigInt(int value) => new BigInt(value);
private readonly BigInteger Value;
public BigInt Negate() => new BigInt(-Value);
public BigInt Add(BigInt addend) => new BigInt(Value + addend.Value);
public BigInt Mul(BigInt multiplicand) => new BigInt(Value * multiplicand.Value);
public static void Test()
{
BigInt one = 1;
BigInt negOne = -one;
var two = one + one;
}
}
```

gives me errors on `-one`

and `one + one`

because, apparently, the type inference doesn't recognise that `BigInt`

can be implicitly coerced to `IRing<BigInt>`

and so match the signatures of the operator overloads.

**Is there a straightforward solution to this which doesn't require reimplementing the operator overloads in each implementing class or explicitly coercing BigInt to IRing<BigInt>?**

## 3 comments

Well, if you want/need to stick with interfaces and structs, you are out of luck, as you already noticed - and which pretty much would be the answer to the question. (1/2) — elgonzo 21 days ago

(2/2) However, if your problem behind your Q is not strictly requiring interfaces and structs, and if your application scenario is not particularly restricted/intolerant towards object allocations, you could turn the interface into an abstract class

`public abstract class RingBase<TRing> where TRing : RingBase<TRing>`

and the`BigInt`

struct into a class inheriting the abstract class. — elgonzo 21 days ago@elgonzo, that's pretty much what I suspected. For my immediate purposes it's not strictly necessary to use an interface, but using an abstract class instead eliminates some interesting future directions. E.g. an orderable subtype and a field subtype couldn't be combined to an orderable field subtype because of the diamond problem. — Peter Taylor 21 days ago