1

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!

Ryan Chou
  • 23
  • 4
  • 1
    _" My goal is to create a `Dictionary` "_ - first of all there is no non-generic version of `INumberBase`. Can you please show some [mre]? – Guru Stron Apr 25 '23 at 09:53
  • 1
    `T` in this case cannot be changed dynamically once created. You can work on it *generically* so that if given a `Dictionary where T : INumberBase` and you don't know what `T` is then you can do addition etc. But you can't make such a constructed `Dictionary` into a `Dictionary` it's just not compatible. Generics aren't simply dynamic types, they represent *placeholders* for types, and once used to create an object cannot be changed within that object. – Charlieface Apr 25 '23 at 09:55

1 Answers1

1

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>.

Guru Stron
  • 102,774
  • 10
  • 95
  • 132