How to multiply a INumber with an int?

How to multiply a INumber with an int?


7

How should I implement the multiplication by int (z * 2) on the last line.

public static TResult Test<TResult>() where TResult : INumber<TResult>
{
    TResult x = TResult.AdditiveIdentity;
    TResult y = TResult.MultiplicativeIdentity;
    TResult z = x * y;
    TResult z2 = z * 2; // <--- this gives the CS0019 error "The operator * cannot be applied to operands of type 'TResult' and 'int'
    return z2;
}

— the suggested solution is to add an interface but it breaks this:
IMultiplyOperators<TResult, int, TResult>

public static void Tester()
{
    Test<decimal>(); // CS0315 Tye type decimal cannot be used as type parameter TResult..... there is no boxing conversion 
}

For now i will inject the function myself and use:

public static TResult Test<TResult>(Func<TResult, int, TResult> mul) where TResult : INumber<TResult>
{
    TResult x = TResult.AdditiveIdentity;
    TResult y = TResult.MultiplicativeIdentity;
    TResult z = x * y;
    TResult z2 = mul(z, 2); 
    return z2;
}

2 Answers
2


7

You need to add the IMultiplyOperators<, ,> interface:

public static TResult Test<TResult>() where TResult : INumber<TResult>, IMultiplyOperators<TResult, int, TResult>
{
    TResult x = TResult.AdditiveIdentity;
    TResult y = TResult.MultiplicativeIdentity;
    TResult z = x * y;
    TResult z2 = z * 2;
    return z2;
}

You can see the list of operator interfaces here.

4

  • Althoug this does work. Look at decimal.cs it doesn't implement the IMultiplyOperators<TResult, int, TResult> interface only IMultiplyOperators<decimal,decimal,decimal>

    – Wouter

    9 hours ago


  • @Wouter I'm afraid I don't actually know the solution for decimal in that case. A simple solution that would work for multiplying by 2 would be just to add z to itself, but that definitely wouldn't scale. Another approach might be to convert integer 2 to TResult using Convert.ChangeType, but I kind of feel that defeats the point of generic maths slightly, so I'm not sure.

    – ProgrammingLlama

    8 hours ago


  • indeed 2 was just an example (could have added z + z). Maybe there is an interface to do the (implicit) conversion?

    – Wouter

    8 hours ago


  • Injection of Func<TResult, int, TResult> multiply to this function will work.

    – Wouter

    8 hours ago


2

I suggest converting 2 to TResult and only then multiply:

   TResult z2 = z * TResult.CreateChecked(2);

Here we create TResult instance from integer value 2, while checking 2 for overflow and similar possible errors (an exception will be thrown if 2 can’t be converted into TResult).

Code:

public static TResult Test<TResult>() where TResult : INumber<TResult>
{
    TResult x = TResult.AdditiveIdentity;
    TResult y = TResult.MultiplicativeIdentity;
    TResult z = x * y;
    TResult z2 = z * TResult.CreateChecked(2);
    return z2;
}

Demo:

Console.WriteLine(Test<decimal>());

Output:

0

Fiddle



Leave a Reply

Your email address will not be published. Required fields are marked *