Интерфейс для объектов, с которыми можно производить арифметические операции

Допустим я хочу написать класс подсчета сраднего арифметического:

public class AverageCounter<T> where T : INumber<T>
{
    public T Sum { get; private set; }
    public int Count { get; private set; }

    public void Add(T el)
    {
        Sum += el;
        Count++;
    }

    public AverageCounter()
    {
        Sum = default;
        Count = 0;
    }
}

Такой код работает, но не хватает одного свойства, с реализацией которого у меня возникли трудности:

public T Average
{
    return Sum / Count;
}

Какой интерфейс использовать, чтобы строчка return Sum / Count; не вызывала проблем?

Возможно нужно написать свой интерфейс? Но тогда как, потому что я не очень понимаю как его реализовывать...


Ответы (1 шт):

Автор решения: rew

В общем то все оказалось просто. Нужно было указать, что T реалезует интерфейсы IAdditionOperators<T, T, T>, IDivisionOperators<T, int, T>

Финальный код класса:

public class AverageCounter<T> 
    where T : IAdditionOperators<T, T, T>, 
    IDivisionOperators<T, int, T>
{
    public T? Sum { get; private set; }
    public int Count { get; private set; }

    public void Add(T el)
    {
        Count++;
        Sum = Sum == null?el:Sum+el;
    }

    public T Average
    {
        get { return Sum / Count; }
    }

    public AverageCounter()
    {
        Sum = default;
        Count = 0;
    }
}

теперь можно использовать AverageCounter как для int, double... Так и для, например, точек:

class Point : IAdditionOperators<Point, Point, Point>, 
    IDivisionOperators<Point, int, Point>
{
    public readonly double X, Y;
    
    public Point(double x, double y)
    {
        X = x;
        Y = y;
    }

    public static Point operator +(Point p1, Point p2)
    {
        return new Point(p1.X + p2.X, p1.Y + p2.Y);
    }
    
    public static Point operator /(Point p1, int n)
    {
        return new Point(p1.X / n, p1.Y / n);
    }

    public override string ToString()
    {
        return $"Point({X}, {Y})";
    }
}
→ Ссылка