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
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 onlyIMultiplyOperators<decimal,decimal,decimal>
– Wouter9 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 toTResult
usingConvert.ChangeType
, but I kind of feel that defeats the point of generic maths slightly, so I'm not sure.– ProgrammingLlama8 hours ago
-
indeed 2 was just an example (could have added z + z). Maybe there is an interface to do the (implicit) conversion?
– Wouter8 hours ago
-
Injection of
Func<TResult, int, TResult> multiply
to this function will work.– Wouter8 hours ago
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