diff --git a/Source/Singulink.Globalization.Currency/Money.GenericMath.cs b/Source/Singulink.Globalization.Currency/Money.GenericMath.cs
new file mode 100644
index 0000000..8b2d041
--- /dev/null
+++ b/Source/Singulink.Globalization.Currency/Money.GenericMath.cs
@@ -0,0 +1,24 @@
+using System.Numerics;
+
+namespace Singulink.Globalization;
+
+#if NET7_0_OR_GREATER
+
+///
+/// Contains generic math implementation of .
+///
+partial struct Money :
+ IAdditionOperators,
+ IAdditionOperators,
+ IComparisonOperators,
+ IDecrementOperators,
+ IDivisionOperators,
+ IDivisionOperators,
+ IIncrementOperators,
+ IMultiplyOperators,
+ ISubtractionOperators,
+ ISubtractionOperators,
+ IUnaryNegationOperators,
+ IUnaryPlusOperators;
+
+#endif
\ No newline at end of file
diff --git a/Source/Singulink.Globalization.Currency/Money.cs b/Source/Singulink.Globalization.Currency/Money.cs
index 6a48cf1..44e9f46 100644
--- a/Source/Singulink.Globalization.Currency/Money.cs
+++ b/Source/Singulink.Globalization.Currency/Money.cs
@@ -133,25 +133,28 @@ public Currency Currency
return x._amount >= y._amount;
}
- public static Money operator +(Money x, Money y) => CreateDefaultable(x._amount + y._amount, CombineCurrencies(x._currency, y._currency));
+ public static Money operator +(Money x, Money y) => CreateDefaultable(x._amount + y._amount, CombineCurrenciesForAddOrSubtract(x._currency, y._currency));
public static Money operator +(Money x, decimal y) => CreateDefaultable(x._amount + y, x._currency);
- public static Money operator +(decimal x, Money y) => y + x;
-
- public static Money operator -(Money x, Money y) => CreateDefaultable(x._amount - y._amount, CombineCurrencies(x._currency, y._currency));
+ public static Money operator -(Money x, Money y) => CreateDefaultable(x._amount - y._amount, CombineCurrenciesForAddOrSubtract(x._currency, y._currency));
public static Money operator -(Money x, decimal y) => CreateDefaultable(x._amount - y, x._currency);
- public static Money operator -(decimal x, Money y) => CreateDefaultable(x - y._amount, y._currency);
-
public static Money operator *(Money x, decimal y) => CreateDefaultable(x._amount * y, x._currency);
- public static Money operator *(decimal x, Money y) => y * x;
-
public static Money operator /(Money x, decimal y) => CreateDefaultable(x._amount / y, x._currency);
- public static Money operator /(decimal x, Money y) => CreateDefaultable(x / y._amount, y._currency);
+ public static decimal operator /(Money x, Money y)
+ {
+ if (x._currency != y._currency)
+ {
+ void Throw() => throw new ArgumentException("Currencies must match to divide money values.");
+ Throw();
+ }
+
+ return x._amount / y._amount;
+ }
public static Money operator ++(Money value)
{
@@ -245,7 +248,7 @@ private static void EnsureSameCurrencyForCompare(Currency? x, Currency? y)
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static Currency? CombineCurrencies(Currency? x, Currency? y)
+ private static Currency? CombineCurrenciesForAddOrSubtract(Currency? x, Currency? y)
{
if (x == y)
return x;
@@ -255,7 +258,7 @@ private static void EnsureSameCurrencyForCompare(Currency? x, Currency? y)
if (y is not null)
{
- static void Throw() => throw new ArgumentException("Currencies must match (or one of the values can be a default value that has no currency associated with it).");
+ static void Throw() => throw new ArgumentException("Currencies must match to add or subtract money values (or one of the values can be a default value that has no currency associated with it).");
Throw();
}
diff --git a/Tests/Singulink.Globalization.Currency.Tests/MoneyTests/Operators.cs b/Tests/Singulink.Globalization.Currency.Tests/MoneyTests/Operators.cs
index 3e8e66b..5dfcd69 100644
--- a/Tests/Singulink.Globalization.Currency.Tests/MoneyTests/Operators.cs
+++ b/Tests/Singulink.Globalization.Currency.Tests/MoneyTests/Operators.cs
@@ -146,40 +146,34 @@ public void Addition_DifferentCurrency_ThrowsArgumentException()
}
[TestMethod]
- public void Addition_OneDefault_ReturnsNonDefaultValue()
+ public void Addition_BothMoneyOneDefault_ReturnsNonDefaultValue()
{
(Usd100 + Money.Default).ShouldBe(Usd100);
(Money.Default + Usd100).ShouldBe(Usd100);
}
[TestMethod]
- public void Addition_BothDefault_ReturnsDefault()
+ public void Addition_BothDefaultMoney_ReturnsDefault()
{
(Money.Default + Money.Default).ShouldBe(Money.Default);
}
[TestMethod]
- public void Addition_MoneyAndDecimal_ReturnsCorrectResult()
- {
- (Usd100 + 200m).ShouldBe(Usd300);
- }
-
- [TestMethod]
- public void Addition_MoneyAndNegativeDecimal_ReturnsCorrectResult()
+ public void Addition_DefaultMoneyAndZero_ReturnsDefault ()
{
- (Usd200 + -100m).ShouldBe(Usd100);
+ (Money.Default + 0m).ShouldBe(Money.Default);
}
[TestMethod]
- public void Addition_DecimalAndMoney_ReturnsCorrectResult()
+ public void Addition_DefaultMoneyAndDecimal_Throws()
{
- (100m + Usd200).ShouldBe(Usd300);
+ Should.Throw(() => Money.Default + 5);
}
[TestMethod]
- public void Addition_NegativeDecimalAndMoney_ReturnsCorrectResult()
+ public void Addition_MoneyAndDecimal_ReturnsCorrectResult()
{
- (-100m + Usd200).ShouldBe(Usd100);
+ (Usd100 + 200m).ShouldBe(Usd300);
}
[TestMethod]
@@ -195,52 +189,40 @@ public void Subtraction_DifferentCurrency_ThrowsArgumentException()
}
[TestMethod]
- public void Subtraction_OneDefault_ReturnsNonDefaultValue()
+ public void Subtraction_BothMoneyOneDefault_ReturnsNonDefaultValue()
{
(Usd100 - Money.Default).ShouldBe(Usd100);
(Money.Default - Usd100).ShouldBe(-Usd100);
}
[TestMethod]
- public void Subtraction_BothDefault_ReturnsDefault()
+ public void Subtraction_BothDefaultMoney_ReturnsDefault()
{
(Money.Default - Money.Default).ShouldBe(Money.Default);
}
[TestMethod]
- public void Subtraction_MoneyAndDecimal_ReturnsCorrectResult()
- {
- (Usd200 - 100m).ShouldBe(Usd100);
- }
-
- [TestMethod]
- public void Subtraction_MoneyAndNegativeDecimal_ReturnsCorrectResult()
- {
- (Usd200 - -100m).ShouldBe(Usd300);
- }
-
- [TestMethod]
- public void Subtraction_DecimalAndMoney_ReturnsCorrectResult()
+ public void Subtraction_DefaultMoneyAndZero_ReturnsDefault()
{
- (200m - Usd100).ShouldBe(Usd100);
+ (Money.Default - 0m).ShouldBe(Money.Default);
}
[TestMethod]
- public void Subtraction_NegativeDecimalAndMoney_ReturnsCorrectResult()
+ public void Subtraction_DefaultMoneyAndDecimal_Throws()
{
- (-100m - Usd200).ShouldBe(-Usd300);
+ Should.Throw(() => Money.Default - 5);
}
[TestMethod]
- public void Subtraction_DecimalMinusMoney_ReturnsCorrectResult()
+ public void Subtraction_MoneyAndDecimal_ReturnsCorrectResult()
{
- (200m - Usd100).ShouldBe(Usd100);
+ (Usd200 - 100m).ShouldBe(Usd100);
}
[TestMethod]
- public void Subtraction_NegativeDecimalMinusMoney_ReturnsCorrectResult()
+ public void Subtraction_MoneyAndNegativeDecimal_ReturnsCorrectResult()
{
- (-100m - Usd200).ShouldBe(-Usd300);
+ (Usd200 - -100m).ShouldBe(Usd300);
}
[TestMethod]
@@ -261,24 +243,6 @@ public void Multiplication_MoneyAndZero_ReturnsZero()
(Usd100 * 0m).ShouldBe(Usd0);
}
- [TestMethod]
- public void Multiplication_DecimalAndMoney_ReturnsCorrectResult()
- {
- (2m * Usd100).ShouldBe(Usd200);
- }
-
- [TestMethod]
- public void Multiplication_NegativeDecimalAndMoney_ReturnsCorrectResult()
- {
- (-2m * Usd100).ShouldBe(-Usd200);
- }
-
- [TestMethod]
- public void Multiplication_ZeroAndMoney_ReturnsZero()
- {
- (0m * Usd100).ShouldBe(Usd0);
- }
-
[TestMethod]
public void Division_MoneyAndDecimal_ReturnsCorrectResult()
{
@@ -304,21 +268,28 @@ public void Division_MoneyAndZero_ThrowsDivideByZeroException()
}
[TestMethod]
- public void Division_DecimalAndMoney_ReturnsCorrectResult()
+ public void Division_SameCurrency_ReturnsCorrectResult()
+ {
+ (Usd200 / Usd100).ShouldBe(2m);
+ }
+
+ [TestMethod]
+ public void Division_OneDefaultMoney_Throws()
{
- (20000m / Usd100).ShouldBe(Usd200);
+ Should.Throw(() => Money.Default / Usd100);
+ Should.Throw(() => Usd100 / Money.Default);
}
[TestMethod]
- public void Division_NegativeDecimalAndMoney_ReturnsCorrectResult()
+ public void Division_DifferentCurrencies_Throws()
{
- (-20000m / Usd100).ShouldBe(UsdMinus200);
+ Should.Throw(() => Usd100 / Cad100);
}
[TestMethod]
- public void Division_DecimalAndZeroMoney_ThrowsDivideByZeroException()
+ public void Division_BothDefaultMoney_ThrowsDivideByZeroException()
{
- Should.Throw(() => 200m / Usd0);
+ Should.Throw(() => Money.Default / Money.Default);
}
[TestMethod]
@@ -343,7 +314,7 @@ public void Decrement_ReturnsCorrectResult()
}
[TestMethod]
- public void Decrement_DefaultVakue_Throws()
+ public void Decrement_DefaultValue_Throws()
{
var value = Money.Default;
Should.Throw(() => value--);