4 ms·
My favorite taunt from the .NET team: according to the .NET Reference Source, built-in numeric types implement an IArithmetic<T> interface... And then they comm
by apk-d 9y ago
My favorite taunt from the .NET team: according to the .NET Reference Source, built-in numeric types implement an IArithmetic<T> interface... And then they comment it out.
http://referencesource.microsoft.com/#mscorlib/system/double.cs,1a65cbdb09544ba1 http://referencesource.microsoft.com/#mscorlib/system/double...
- louthy 9y agoHere's an ad-hoc polymorphic way of dealing with numeric types in C# without the boxing that would be caused by using an IArithmetic interface: public interface Num<A> { A Add(A x, A y); A Subtract(A x, A y); A Multiply(A x, A y); A Divide(A x, A y); A FromInteger(int value); } public struct NumInt : Num<int> { public int Add(int x, int y) => x + y; public int Subtract(int x, int y) => x - y; public int Multiply(int x, int y) => x * y; public int Divide(int x, int y) => x / y; public int FromInteger(int value) => value; } public struct NumDouble : Num<double> { public double Add(double x, double y) => x + y; public double Subtract(double x, double y) => x - y; public double Multiply(double x, double y) => x * y; public double Divide(double x, double y) => x / y; public double FromInteger(int value) => (double)value; } public struct NumBigInt : Num<BigInteger> { public BigInteger Add(BigInteger x, BigInteger y) => x + y; public BigInteger Subtract(BigInteger x, BigInteger y) => x - y; public BigInteger Multiply(BigInteger x, BigInteger y) => x * y; public BigInteger Divide(BigInteger x, BigInteger y) => x / y; public BigInteger FromInteger(int value) => (BigInteger)value; } public static class TestGenericNums { public static void Test() { var a = DoubleIt<NumInt, int>(10); // 20 var b = SquareIt<NumInt, int>(10); // 100 var c = NegateIt<NumInt, int>(10); // -10 var t = DoubleIt<NumDouble, double>(10); // 20 var u = SquareIt<NumDouble, double>(10); // 100 var v = NegateIt<NumDouble, double>(10); // -10 var x = DoubleIt<NumBigInt, BigInteger>(10); // 20 var y = SquareIt<NumBigInt, BigInteger>(10); // 100 var z = NegateIt<NumBigInt, BigInteger>(10); // -10 } public static A DoubleIt<NumA, A>(A value) where NumA : struct, Num<A> => default(NumA).Add(value, value); public static A SquareIt<NumA, A>(A value) where NumA : struct, Num<A> => default(NumA).Multiply(value, value); public static A NegateIt<NumA, A>(A value) where NumA : struct, Num<A> => default(NumA).Subtract(default(NumA).FromInteger(0), value); }
- colejohnson66 9y agoThat doesn't account for overflow, though...
- louthy 9y agoSorry, I don't follow?
- colejohnson66 9y agoThe .NET implementation detects overflow and reports it back. This doesn't.
- louthy 9y agoThis: var x = DoubleIt<NumInt, int>(Int32.MaxValue); // 20 Performs exactly the same as this: var a = Int32.MaxValue; var b = Int32.MaxValue; var c = a + b; DoubleIt calls NumInt.Add which invokes the same code, why wouldn't it work in exactly the same way?
- lloydjatkinson 9y agoI saw that too! WTF!