I want my container to do element-wise arithmetic, but I can't figure out how to make an operator definition accept type parameters.

public static Stats<T> operator + (Stats<T> a, Stats<T2> b) 
    where T2 : System.Numerics.IAdditionOperators<T2,T,T>

I'm a python programmer trying to learn C# by exploring game development. My goal is to create a Dictionary<string,INumberBase> to hold the stats of a player that accepts keys from a limited set and supports arithmetic operations such as addition and multiplication to be performed element-wise by key. My current solution has been to define a class that contains a regular dictionary and define operator methods. I would also like it to support casting its dictionary to a different numerical type i.e. Stats<byte> to Stats<ulong> or to use overflow checking to increase the memory size dynamically.

Sorry if this is a dumb question. I don't have any experience with type declarations and interfaces since python takes care of all of that implicitly.

I tried to use operator methods but I don't know how to declare T2 in the example above. I also tried to define casting methods but ran into the same problem, though I'm not sure I was doing that properly to begin with.

I could simply replace T2 with int and every other numeric type, but that seems like a code smell. I could also define a public multiply<T2> method, but that also seems like a code smell when there's an operator override syntax built into the language.

Edit:

My new solution is to subclass Stats<ulong> and Stats<byte> and define an operator on Stats<byte> that multiplication by uint gives a Stats<ulong> instance. Thanks everyone for all your input and helping me understand interfaces and dynamic types!

1

There are 1 best solutions below

0
On

C# does not support generic operator overloading - see this discussion, operator declarations does not allow syntax for declaring the generic type parameters - spec. So you need either to manipulate on the same types:

class Stats<T> where T : IAdditionOperators<T,T,T>
{
    public T Stat { get; set; }
    public static Stats<T> operator+(Stats<T> a, Stats<T> b) => new() { Stat = a.Stat + b.Stat };
}

Or declare custom methods:

class Stats<T> where T : IAdditionOperators<T,T,T>
{
    public T Stat { get; set; }

    public static Stats<T> operator+(Stats<T> a, Stats<T> b) => new() { Stat = a.Stat + b.Stat };

    public Stats<T> Plus<T2>(Stats<T2> s) where T2 : IAdditionOperators<T2, T, T>, IAdditionOperators<T2, T2, T2> =>
        new() { Stat = s.Stat + Stat  };
}

Also note that there is no non-generic INumberBase interface, so you can't do Dictionary<string, INumberBase>.