diff --git a/UnitsNet.Tests/AffineQuantityExtensionsTest.cs b/UnitsNet.Tests/AffineQuantityExtensionsTest.cs index 5da68a2030..85bb4ce95c 100644 --- a/UnitsNet.Tests/AffineQuantityExtensionsTest.cs +++ b/UnitsNet.Tests/AffineQuantityExtensionsTest.cs @@ -1,8 +1,11 @@ // Licensed under MIT No Attribution, see LICENSE file at the root. // Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet. +using System.Diagnostics.CodeAnalysis; + namespace UnitsNet.Tests; +[SuppressMessage("ReSharper", "InvokeAsExtensionMethod")] public class AffineQuantityExtensionsTest { [Theory] @@ -45,7 +48,7 @@ public void Equals_WithToleranceAtTheLimit_ReturnsTrue() } [Fact] - public void Equals_Temperature_TemperatureDelta_ThrowsArgumentOutOfRangeException_ForNegativeTolerance() + public void Equals_WithNegativeTolerance_ThrowsArgumentOutOfRangeException() { var temperature1 = Temperature.FromDegreesCelsius(25.0); var temperature2 = Temperature.FromDegreesCelsius(25.0); @@ -54,58 +57,17 @@ public void Equals_Temperature_TemperatureDelta_ThrowsArgumentOutOfRangeExceptio Assert.Throws(() => temperature1.Equals(temperature2, negativeTolerance)); } - [Theory] - [InlineData(25.0, 25.0, 0.1, true)] // Equal values - // [InlineData(25.0, 25.1, 0.1, true)] // Within tolerance (but fails due to rounding) - [InlineData(25.0, 25.1, 0.10001, true)] // Within tolerance - [InlineData(25.0, 25.2, 0.1, false)] // Outside tolerance - [InlineData(25.0, 25.0, 0.0, true)] // Zero tolerance, equal values - [InlineData(25.0, 25.1, 0.0, false)] // Zero tolerance, different values - public void Equals_Temperature_IQuantity(double value1, double value2, double toleranceValue, bool expected) - { - var temperature1 = Temperature.FromDegreesCelsius(value1); - IQuantity temperature2 = Temperature.FromDegreesCelsius(value2); - var tolerance = TemperatureDelta.FromDegreesCelsius(toleranceValue); - - var result = temperature1.Equals(temperature2, tolerance); - - Assert.Equal(expected, result); - } - - [Fact] - public void Equals_Temperature_IQuantity_WithDifferentType_ReturnsFalse() - { - var temperature1 = Temperature.FromDegreesCelsius(25.0); - IQuantity length = Length.From(1, LengthUnit.Meter); - var tolerance = TemperatureDelta.FromDegreesCelsius(1); - - var result = temperature1.Equals(length, tolerance); - - Assert.False(result); - } - [Fact] public void Equals_WithNullOther_ReturnsFalse() { var quantity = Temperature.FromDegreesCelsius(25.0); var tolerance = TemperatureDelta.FromDegreesCelsius(25.0); - var result = quantity.Equals(null, tolerance); + var result = AffineQuantityExtensions.Equals(quantity, (Temperature?)null, tolerance); Assert.False(result); } - [Fact] - public void Equals_ThrowsArgumentOutOfRangeException_ForNegativeTolerance() - { - var temperature1 = Temperature.FromDegreesCelsius(25.0); - var temperature2 = Temperature.FromDegreesCelsius(25.0); - var negativeTolerance = TemperatureDelta.FromDegreesCelsius(-0.1); - - Assert.Throws(() => temperature1.Equals(temperature2, negativeTolerance)); - Assert.Throws(() => temperature1.Equals((IQuantity)temperature2, negativeTolerance)); - } - [Theory] [InlineData(new[] { 25.0, 30.0, 35.0 }, 30.0)] // Average of three values [InlineData(new[] { 25.0 }, 25.0)] // Single value @@ -114,7 +76,7 @@ public void Average_Temperature(double[] values, double expectedAverage) Temperature[] temperatures = Array.ConvertAll(values, value => Temperature.FromDegreesCelsius(value)); Temperature result = temperatures.Average(); - + Assert.Equal(expectedAverage, result.Value); Assert.Equal(TemperatureUnit.DegreeCelsius, result.Unit); } @@ -147,7 +109,7 @@ public void Average_Temperature_ThrowsArgumentNullException_ForNullCollection() public void Average_Temperature_ThrowsInvalidOperationException_ForEmptyCollection() { Temperature[] temperatures = []; - + Assert.Throws(() => temperatures.Average()); } @@ -163,7 +125,7 @@ public void Average_Temperature_WithUnit(double[] values, TemperatureUnit unit, Assert.Equal(expectedAverage, result.Value); Assert.Equal(unit, result.Unit); } - + [Fact] public void Average_TemperaturesWithDifferentUnits_WithTargetUnit() { diff --git a/UnitsNet.Tests/Extensions/QuantityExtensionsTests.cs b/UnitsNet.Tests/Extensions/QuantityExtensionsTests.cs new file mode 100644 index 0000000000..09a9dc13fb --- /dev/null +++ b/UnitsNet.Tests/Extensions/QuantityExtensionsTests.cs @@ -0,0 +1,228 @@ +// Licensed under MIT No Attribution, see LICENSE file at the root. +// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet. + +using System.Diagnostics.CodeAnalysis; + +namespace UnitsNet.Tests.Extensions; + +[SuppressMessage("ReSharper", "InvokeAsExtensionMethod")] +public class QuantityExtensionsTests +{ + [Theory] + [InlineData(25.0, 25.0, 0.1, true)] // Equal values + // [InlineData(25.0, 25.1, 0.1, true)] // Within tolerance (but fails due to rounding) + [InlineData(25.0, 25.1, 0.10001, true)] // Within tolerance + [InlineData(25.0, 25.2, 0.1, false)] // Outside tolerance + [InlineData(25.0, 25.0, 0.0, true)] // Zero tolerance, equal values + [InlineData(25.0, 25.1, 0.0, false)] // Zero tolerance, different values + public void Equals_Affine_IQuantity(double value1, double value2, double toleranceValue, bool expected) + { + var temperature1 = Temperature.FromDegreesCelsius(value1); + IQuantity temperature2 = Temperature.FromDegreesCelsius(value2); + var tolerance = TemperatureDelta.FromDegreesCelsius(toleranceValue); + + var result = QuantityExtensions.Equals(temperature1, temperature2, tolerance); + + Assert.Equal(expected, result); + } + + [Fact] + public void Equals_Affine_IQuantity_WithDifferentType_ReturnsFalse() + { + var temperature1 = Temperature.FromDegreesCelsius(25.0); + IQuantity length = Length.From(1, LengthUnit.Meter); // no other affine quantity to compare with + var tolerance = TemperatureDelta.FromDegreesCelsius(1); + + var result = QuantityExtensions.Equals(temperature1, length, tolerance); + + Assert.False(result); + } + + [Fact] + public void Equals_Linear_IQuantity_WithDifferentType_ReturnsFalse() + { + var mass = Mass.FromKilograms(25.0); + IQuantity length = Length.From(1, LengthUnit.Meter); + var tolerance = Mass.FromKilograms(1); + + var result = QuantityExtensions.Equals(mass, length, tolerance); + + Assert.False(result); + } + + [Fact] + public void Equals_Logarithmic_IQuantity_WithDifferentType_ReturnsFalse() + { + var powerRatio = PowerRatio.FromDecibelWatts(25.0); + IQuantity level = Level.From(1, LevelUnit.Decibel); + var tolerance = PowerRatio.FromDecibelWatts(1); + + var result = QuantityExtensions.Equals(powerRatio, level, tolerance); + + Assert.False(result); + } + + [Fact] + public void Equals_Affine_WithNullOther_ReturnsFalse() + { + var quantity = Temperature.FromDegreesCelsius(25.0); + var tolerance = TemperatureDelta.FromDegreesCelsius(25.0); + + var result = QuantityExtensions.Equals(quantity, null, tolerance); + + Assert.False(result); + } + + [Fact] + public void Equals_Linear_WithNullOther_ReturnsFalse() + { + var quantity = Length.FromMeters(2.0); + var tolerance = Length.FromMeters(0.1); + + var result = QuantityExtensions.Equals(quantity, null, tolerance); + + Assert.False(result); + } + + [Fact] + public void Equals_Logarithmic_WithNullOther_ReturnsFalse() + { + var quantity = PowerRatio.FromDecibelWatts(2.0); + var tolerance = PowerRatio.FromDecibelWatts(0.1); + + var result = QuantityExtensions.Equals(quantity, null, tolerance); + + Assert.False(result); + } + + [Theory] + [InlineData(2.0, 2.0, 0.1, true)] + // [InlineData(2.0, 2.1, 0.1, true)] // should be equal but fails due to rounding + [InlineData(2.0, 2.1, 0.10001, true)] + [InlineData(2.0, 2.2, 0.1, false)] + [InlineData(2.0, 2.0, 0.0, true)] + [InlineData(2.0, 2.1, 0.0, false)] + public void IQuantity_Equals_IQuantity_ReturnsExpectedResult(double value1, double value2, double tolerance, bool expected) + { + IQuantity untypedQuantity1 = Length.FromMeters(value1); + IQuantity untypedQuantity2 = Length.FromMeters(value2); + IQuantity untypedToleranceQuantity = Length.FromMeters(tolerance); + + var result = QuantityExtensions.Equals(untypedQuantity1, untypedQuantity2, untypedToleranceQuantity); + + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(2.0, 2.0, 0.1, true)] + // [InlineData(2.0, 2.1, 0.1, true)] // should be equal but fails due to rounding + [InlineData(2.0, 2.1, 0.10001, true)] + [InlineData(2.0, 2.2, 0.1, false)] + [InlineData(2.0, 2.0, 0.0, true)] + [InlineData(2.0, 2.1, 0.0, false)] + public void Equals_WithUntypedOtherAndTolerance_ReturnsExpectedResult(double value1, double value2, double tolerance, bool expected) + { + var quantity1 = Length.FromMeters(value1); + IQuantity untypedQuantity2 = Length.FromMeters(value2); + var toleranceQuantity = Length.FromMeters(tolerance); + + var result = QuantityExtensions.Equals(quantity1, untypedQuantity2, toleranceQuantity); + + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(2.0, 2.0, 0.1, true)] + // [InlineData(2.0, 2.1, 0.1, true)] // should be equal but fails due to rounding + [InlineData(2.0, 2.1, 0.10001, true)] + [InlineData(2.0, 2.2, 0.1, false)] + [InlineData(2.0, 2.0, 0.0, true)] + [InlineData(2.0, 2.1, 0.0, false)] + public void Equals_IQuantityWithTolerance_ReturnsExpectedResult(double value1, double value2, double tolerance, bool expected) + { + var quantity1 = Length.FromMeters(value1); + IQuantity quantity2 = Length.FromMeters(value2); + var toleranceQuantity = Length.FromMeters(tolerance); + + var result = QuantityExtensions.Equals(quantity1, quantity2, toleranceQuantity); + + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(1, 2)] + [InlineData(100, 110)] + [InlineData(100, 90)] + public void Equals_Logarithmic_IQuantity_ComparesInLinearSpace(double firstValue, double secondValue) + { + var quantity = PowerRatio.FromDecibelWatts(firstValue); + var otherQuantity = PowerRatio.FromDecibelWatts(secondValue); + PowerRatio maxTolerance = quantity > otherQuantity ? quantity - otherQuantity : otherQuantity - quantity; + PowerRatio largerTolerance = maxTolerance * 1.1; + PowerRatio smallerTolerance = maxTolerance / 1.1; + Assert.True(QuantityExtensions.Equals(quantity, (IQuantity)quantity, PowerRatio.Zero)); + Assert.True(QuantityExtensions.Equals(quantity, (IQuantity)quantity, maxTolerance)); + Assert.True(QuantityExtensions.Equals(quantity, (IQuantity)otherQuantity, largerTolerance)); + Assert.False(QuantityExtensions.Equals(quantity, (IQuantity)otherQuantity, smallerTolerance)); + // note: it's currently not possible to test this due to the rounding error from (quantity - otherQuantity) + // Assert.True(quantity.Equals((IQuantity)otherQuantity, maxTolerance)); + } + + [Fact] + public void Equals_Logarithmic_NullQuantity_ReturnsFalse() + { + var quantity = PowerRatio.FromDecibelWatts(1); + var tolerance = PowerRatio.FromDecibelWatts(1); + Assert.False(QuantityExtensions.Equals(quantity, null, tolerance)); + } + + [Fact(Skip = "Currently throws a NotImplementedException")] + public void Equals_Linear_IQuantity_WithUnknownUnits_ThrowsUnitNotFoundException() + { + var quantity = Length.FromMeters(1); + var invalidQuantity = new Length(1, (LengthUnit)(-1)); + Assert.Throws(() => invalidQuantity.Equals((IQuantity)quantity, quantity)); + Assert.Throws(() => quantity.Equals((IQuantity)invalidQuantity, quantity)); + Assert.Throws(() => quantity.Equals((IQuantity)quantity, invalidQuantity)); + } + + [Fact(Skip = "Currently throws a NotImplementedException")] + public void Equals_Logarithmic_IQuantity_WithUnknownUnits_ThrowsUnitNotFoundException() + { + var quantity = PowerRatio.FromDecibelWatts(1); + var invalidQuantity = new PowerRatio(1, (PowerRatioUnit)(-1)); + Assert.Throws(() => QuantityExtensions.Equals(invalidQuantity, (IQuantity)quantity, quantity)); + Assert.Throws(() => QuantityExtensions.Equals(quantity, (IQuantity)invalidQuantity, quantity)); + Assert.Throws(() => QuantityExtensions.Equals(quantity, (IQuantity)quantity, invalidQuantity)); + } + + [Fact] + public void Equals_Affine_WithNegativeTolerance_ThrowsArgumentOutOfRangeException() + { + var quantity = Temperature.FromDegreesCelsius(20); + var other = Temperature.FromDegreesCelsius(21); + var tolerance = TemperatureDelta.FromDegreesCelsius(-0.1); + + Assert.Throws(() => quantity.Equals((IQuantity)other, tolerance)); + } + + [Fact] + public void Equals_Linear_WithNegativeTolerance_ThrowsArgumentOutOfRangeException() + { + var quantity = Length.FromMeters(2.0); + var other = Length.FromMeters(2.0); + var tolerance = Length.FromMeters(-0.1); + + Assert.Throws(() => quantity.Equals((IQuantity)other, tolerance)); + } + + [Fact] + public void Equals_Logarithmic_WithNegativeTolerance_DoesNotThrowArgumentOutOfRangeException() + { + // note: unlike with vector quantities- a small tolerance maybe positive in one unit and negative in another + var quantity = PowerRatio.FromDecibelWatts(1); + var negativeTolerance = PowerRatio.FromDecibelWatts(-1); + Assert.True(QuantityExtensions.Equals(quantity, (IQuantity)quantity, negativeTolerance)); + } + +} diff --git a/UnitsNet.Tests/LinearQuantityExtensionsTest.cs b/UnitsNet.Tests/LinearQuantityExtensionsTest.cs index 55305f4c7d..8f4057d3fb 100644 --- a/UnitsNet.Tests/LinearQuantityExtensionsTest.cs +++ b/UnitsNet.Tests/LinearQuantityExtensionsTest.cs @@ -1,8 +1,11 @@ // Licensed under MIT No Attribution, see LICENSE file at the root. // Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet. +using System.Diagnostics.CodeAnalysis; + namespace UnitsNet.Tests; +[SuppressMessage("ReSharper", "InvokeAsExtensionMethod")] public class LinearQuantityExtensionsTest { [Theory] @@ -44,35 +47,17 @@ public void Equals_WithToleranceAtTheLimit_ReturnsTrue() }); } - [Theory] - [InlineData(2.0, 2.0, 0.1, true)] - // [InlineData(2.0, 2.1, 0.1, true)] // should be equal but fails due to rounding - [InlineData(2.0, 2.1, 0.10001, true)] - [InlineData(2.0, 2.2, 0.1, false)] - [InlineData(2.0, 2.0, 0.0, true)] - [InlineData(2.0, 2.1, 0.0, false)] - public void Equals_IQuantityWithTolerance_ReturnsExpectedResult(double value1, double value2, double tolerance, bool expected) - { - var quantity1 = Length.FromMeters(value1); - IQuantity quantity2 = Length.FromMeters(value2); - var toleranceQuantity = Length.FromMeters(tolerance); - - var result = quantity1.Equals(quantity2, toleranceQuantity); - - Assert.Equal(expected, result); - } - [Fact] public void Equals_WithNullOther_ReturnsFalse() { var quantity = Length.FromMeters(2.0); var tolerance = Length.FromMeters(0.1); - var result = quantity.Equals(null, tolerance); + var result = LinearQuantityExtensions.Equals(quantity, (Length?)null, tolerance); Assert.False(result); } - + [Fact(Skip = "Currently throws a NotImplementedException")] public void Equals_TQuantity_WithUnknownUnits_ThrowsUnitNotFoundException() { @@ -83,16 +68,6 @@ public void Equals_TQuantity_WithUnknownUnits_ThrowsUnitNotFoundException() Assert.Throws(() => quantity.Equals(quantity, invalidQuantity)); } - [Fact(Skip = "Currently throws a NotImplementedException")] - public void Equals_IQuantity_WithUnknownUnits_ThrowsUnitNotFoundException() - { - var quantity = Length.FromMeters(1); - var invalidQuantity = new Length(1, (LengthUnit)(-1)); - Assert.Throws(() => invalidQuantity.Equals((IQuantity)quantity, quantity)); - Assert.Throws(() => quantity.Equals((IQuantity)invalidQuantity, quantity)); - Assert.Throws(() => quantity.Equals((IQuantity)quantity, invalidQuantity)); - } - [Fact] public void Equals_WithNegativeTolerance_ThrowsArgumentOutOfRangeException() { @@ -101,7 +76,6 @@ public void Equals_WithNegativeTolerance_ThrowsArgumentOutOfRangeException() var tolerance = Length.FromMeters(-0.1); Assert.Throws(() => quantity.Equals(other, tolerance)); - Assert.Throws(() => quantity.Equals((IQuantity)other, tolerance)); } [Fact] diff --git a/UnitsNet.Tests/LogarithmicQuantityExtensionsTest.cs b/UnitsNet.Tests/LogarithmicQuantityExtensionsTest.cs index a77ae31b8c..dc721e706a 100644 --- a/UnitsNet.Tests/LogarithmicQuantityExtensionsTest.cs +++ b/UnitsNet.Tests/LogarithmicQuantityExtensionsTest.cs @@ -2,8 +2,11 @@ // Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet. +using System.Diagnostics.CodeAnalysis; + namespace UnitsNet.Tests; +[SuppressMessage("ReSharper", "InvokeAsExtensionMethod")] public class LogarithmicQuantityExtensionsTest { [Theory] @@ -21,37 +24,18 @@ public void Equals_TQuantity_ComparesInLinearSpace(double firstValue, double sec Assert.True(quantity.Equals(quantity, maxTolerance)); Assert.True(quantity.Equals(otherQuantity, largerTolerance)); Assert.False(quantity.Equals(otherQuantity, smallerTolerance)); - // note: it's currently not possible to test this due to the rounding error from (quantity - otherQuantity) + // note: it's currently not possible to test this due to the rounding error from (quantity - otherQuantity) // Assert.True(quantity.Equals(otherQuantity, maxTolerance)); } - [Theory] - [InlineData(1, 2)] - [InlineData(100, 110)] - [InlineData(100, 90)] - public void Equals_IQuantity_ComparesInLinearSpace(double firstValue, double secondValue) - { - var quantity = PowerRatio.FromDecibelWatts(firstValue); - var otherQuantity = PowerRatio.FromDecibelWatts(secondValue); - PowerRatio maxTolerance = quantity > otherQuantity ? quantity - otherQuantity : otherQuantity - quantity; - PowerRatio largerTolerance = maxTolerance * 1.1; - PowerRatio smallerTolerance = maxTolerance / 1.1; - Assert.True(quantity.Equals((IQuantity)quantity, PowerRatio.Zero)); - Assert.True(quantity.Equals((IQuantity)quantity, maxTolerance)); - Assert.True(quantity.Equals((IQuantity)otherQuantity, largerTolerance)); - Assert.False(quantity.Equals((IQuantity)otherQuantity, smallerTolerance)); - // note: it's currently not possible to test this due to the rounding error from (quantity - otherQuantity) - // Assert.True(quantity.Equals((IQuantity)otherQuantity, maxTolerance)); - } - [Fact] public void Equals_NullQuantity_ReturnsFalse() { var quantity = PowerRatio.FromDecibelWatts(1); var tolerance = PowerRatio.FromDecibelWatts(1); - Assert.False(quantity.Equals(null, tolerance)); + Assert.False(LogarithmicQuantityExtensions.Equals(quantity, (PowerRatio?)null, tolerance)); } - + [Fact(Skip = "Currently throws a NotImplementedException")] public void Equals_TQuantity_WithUnknownUnits_ThrowsUnitNotFoundException() { @@ -61,16 +45,6 @@ public void Equals_TQuantity_WithUnknownUnits_ThrowsUnitNotFoundException() Assert.Throws(() => quantity.Equals(invalidQuantity, quantity)); Assert.Throws(() => quantity.Equals(quantity, invalidQuantity)); } - - [Fact(Skip = "Currently throws a NotImplementedException")] - public void Equals_IQuantity_WithUnknownUnits_ThrowsUnitNotFoundException() - { - var quantity = PowerRatio.FromDecibelWatts(1); - var invalidQuantity = new PowerRatio(1, (PowerRatioUnit)(-1)); - Assert.Throws(() => invalidQuantity.Equals((IQuantity)quantity, quantity)); - Assert.Throws(() => quantity.Equals((IQuantity)invalidQuantity, quantity)); - Assert.Throws(() => quantity.Equals((IQuantity)quantity, invalidQuantity)); - } [Fact] public void Equals_WithNegativeTolerance_DoesNotThrowArgumentOutOfRangeException() @@ -79,7 +53,6 @@ public void Equals_WithNegativeTolerance_DoesNotThrowArgumentOutOfRangeException var quantity = PowerRatio.FromDecibelWatts(1); var negativeTolerance = PowerRatio.FromDecibelWatts(-1); Assert.True(quantity.Equals(quantity, negativeTolerance)); - Assert.True(quantity.Equals((IQuantity)quantity, negativeTolerance)); } [Fact] @@ -167,7 +140,7 @@ public void Sum_SingleQuantity_WithSelector_ReturnsCorrectSum(double value, Powe IEnumerable quantities = new List { quantity }; PowerRatio result = quantities.Sum(x => x); - + Assert.Equal(quantity.Value, result.Value, 1e-5); Assert.Equal(quantity.Unit, result.Unit); } @@ -223,7 +196,7 @@ public void Sum_WithSelector_ReturnsCorrectSum(double value1, PowerRatioUnit uni PowerRatio expectedValue = quantity1 + quantity2; PowerRatio result = quantities.Sum(x => x); - + Assert.Equal(expectedValue.Value, result.Value, 1e-5); Assert.Equal(unit1, result.Unit); } @@ -251,7 +224,7 @@ public void Sum_WithSelectorAndUnit_ReturnsCorrectSum(double value1, PowerRatioU PowerRatio expectedValue = quantity1 + quantity2; PowerRatio result = quantities.Sum(x => x, unit1); - + Assert.Equal(expectedValue.Value, result.Value, 1e-5); Assert.Equal(unit1, result.Unit); } @@ -333,7 +306,7 @@ public void ArithmeticMean_SingleQuantity_WithSelector_ReturnsCorrectMean(double IEnumerable quantities = new List { quantity }; PowerRatio result = quantities.ArithmeticMean(x => x); - + Assert.Equal(quantity.Value, result.Value, 1e-5); Assert.Equal(quantity.Unit, result.Unit); } diff --git a/UnitsNet/Extensions/AffineQuantityExtensions.cs b/UnitsNet/Extensions/AffineQuantityExtensions.cs index 3477b5b47e..4dfd87687b 100644 --- a/UnitsNet/Extensions/AffineQuantityExtensions.cs +++ b/UnitsNet/Extensions/AffineQuantityExtensions.cs @@ -14,20 +14,22 @@ namespace UnitsNet; public static class AffineQuantityExtensions { #if NET - /// - public static bool Equals(this TQuantity quantity, TQuantity? other, TOffset tolerance) - where TQuantity : IAffineQuantity, ISubtractionOperators + /// + public static bool Equals(this TQuantity quantity, TOther? other, TOffset tolerance) + where TQuantity : IAffineQuantity, ISubtractionOperators + where TOther : struct, IAffineQuantity where TOffset : IQuantityOfType, IAdditiveIdentity { - return other != null && quantity.EqualsAbsolute(other, tolerance); + return other is not null && EqualsNotNull(quantity, other.Value, tolerance); } - /// - public static bool Equals(this TQuantity quantity, IQuantity? other, TOffset tolerance) - where TQuantity : IAffineQuantity, ISubtractionOperators + /// + public static bool Equals(this TQuantity quantity, TOther? other, TOffset tolerance) + where TQuantity : IAffineQuantity, ISubtractionOperators + where TOther : IAffineQuantity where TOffset : IQuantityOfType, IAdditiveIdentity { - return other is TQuantity otherInstance && quantity.EqualsAbsolute(otherInstance, tolerance); + return other is not null && EqualsNotNull(quantity, other, tolerance); } /// @@ -47,6 +49,7 @@ public static bool Equals(this TQuantity quantity, IQuantity /// /// /// The type of the quantity being compared. + /// The type of the other quantity being compared. /// The type of the tolerance quantity. /// The quantity to compare. /// The other quantity to compare to. @@ -58,8 +61,9 @@ public static bool Equals(this TQuantity quantity, IQuantity /// It is generally advised against specifying "zero" tolerance, preferring the use of the default equality /// comparer, which is significantly more performant. /// - private static bool EqualsAbsolute(this TQuantity quantity, TQuantity other, TOffset tolerance) - where TQuantity : IAffineQuantity, ISubtractionOperators + private static bool EqualsNotNull(TQuantity quantity, TOther other, TOffset tolerance) + where TQuantity : IAffineQuantity, ISubtractionOperators + where TOther : IAffineQuantity where TOffset : IQuantityOfType, IAdditiveIdentity { if (double.IsNegative(tolerance.Value)) diff --git a/UnitsNet/Extensions/LinearQuantityExtensions.cs b/UnitsNet/Extensions/LinearQuantityExtensions.cs index c029459908..675b96248d 100644 --- a/UnitsNet/Extensions/LinearQuantityExtensions.cs +++ b/UnitsNet/Extensions/LinearQuantityExtensions.cs @@ -11,21 +11,20 @@ namespace UnitsNet; /// public static class LinearQuantityExtensions { - /// - public static bool Equals(this TQuantity quantity, TOther? other, TTolerance tolerance) + /// + public static bool Equals(this TQuantity quantity, TOther? other, TQuantity tolerance) where TQuantity : ILinearQuantity - where TOther : IQuantityOfType - where TTolerance : IQuantityOfType + where TOther : struct, ILinearQuantity { - return other != null && quantity.EqualsAbsolute(other, tolerance); + return other is not null && EqualsNotNull(quantity, other.Value, tolerance); } - /// - public static bool Equals(this TQuantity quantity, IQuantity? other, TTolerance tolerance) + /// + public static bool Equals(this TQuantity quantity, TOther? other, TQuantity tolerance) where TQuantity : ILinearQuantity - where TTolerance : IQuantityOfType + where TOther : ILinearQuantity { - return other is TQuantity otherInstance && quantity.EqualsAbsolute(otherInstance, tolerance); + return other is not null && EqualsNotNull(quantity, other, tolerance); } /// @@ -45,7 +44,6 @@ public static bool Equals(this TQuantity quantity, IQuant /// /// The type of the quantity being compared. /// The type of the other quantity being compared. - /// The type of the tolerance quantity. /// The quantity to compare. /// The other quantity to compare to. /// The absolute tolerance value. Must be greater than or equal to zero. @@ -56,10 +54,9 @@ public static bool Equals(this TQuantity quantity, IQuant /// It is generally advised against specifying "zero" tolerance, preferring the use of the default equality /// comparer, which is significantly more performant. /// - private static bool EqualsAbsolute(this TQuantity quantity, TOther other, TTolerance tolerance) + private static bool EqualsNotNull(TQuantity quantity, TOther other, TQuantity tolerance) where TQuantity : ILinearQuantity - where TOther : IQuantityOfType - where TTolerance : IQuantityOfType + where TOther : ILinearQuantity { UnitKey quantityUnit = quantity.UnitKey; return Comparison.EqualsAbsolute(quantity.Value, other.GetValue(quantityUnit), tolerance.GetValue(quantityUnit)); @@ -88,7 +85,7 @@ public static TQuantity Sum(this IEnumerable quantities) { return default!; } - + return (TQuantity)UnitsNetSetup.Default.QuantityInfoLookup.GetQuantityInfo(typeof(TQuantity)).Zero; #endif } @@ -107,7 +104,7 @@ public static TQuantity Sum(this IEnumerable quantities) return firstQuantity.QuantityInfo.Create(sumOfValues, resultUnit); #endif } - + /// /// Computes the sum of a sequence of quantities by applying a specified selector function to each element of the /// sequence. diff --git a/UnitsNet/Extensions/LogarithmicQuantityExtensions.cs b/UnitsNet/Extensions/LogarithmicQuantityExtensions.cs index 7f28720e05..fbc32fc2fc 100644 --- a/UnitsNet/Extensions/LogarithmicQuantityExtensions.cs +++ b/UnitsNet/Extensions/LogarithmicQuantityExtensions.cs @@ -30,59 +30,25 @@ private static double RootN(double number, int n) #endif } - /// - public static bool Equals(this TQuantity quantity, TOther? other, TTolerance tolerance) + /// + public static bool Equals(this TQuantity quantity, TOther? other, TQuantity tolerance) where TQuantity : ILogarithmicQuantity - where TOther : IQuantityOfType - where TTolerance : IQuantityOfType + where TOther : ILogarithmicQuantity { - return other is not null && quantity.EqualsAbsolute(other, tolerance); + return other is not null && EqualsNotNull(quantity, other, tolerance); } - /// - public static bool Equals(this TQuantity quantity, IQuantity? other, TTolerance tolerance) + /// + public static bool Equals(this TQuantity quantity, TOther? other, TQuantity tolerance) where TQuantity : ILogarithmicQuantity - where TTolerance : IQuantityOfType + where TOther : struct, ILogarithmicQuantity { - return other is TQuantity otherInstance && quantity.EqualsAbsolute(otherInstance, tolerance); + return other is not null && EqualsNotNull(quantity, other.Value, tolerance); } - /// - /// Compares the logarithmic equality of the current quantity to another quantity, given a specified tolerance. - /// - /// In this example, the two power ratios will be considered equal if the value of `b` is within 0.5 decibels of - /// `a`. - /// - /// var a = PowerRatio.FromDecibelMilliwatts(30); // Reference power of 1 mW - /// var b = PowerRatio.FromDecibelMilliwatts(29.8); // Slightly less than `a` - /// var tolerance = PowerRatio.FromDecibelMilliwatts(0.5); // 0.5 dBm tolerance - /// a.Equals(b, tolerance); // true, as 30 dBm equals 29.8 dBm +/- 0.5 dBm - /// - /// - /// - /// The type of the quantity being compared. - /// The type of the other quantity being compared. - /// The type of the tolerance value. - /// The logarithmic quantity to compare. - /// The other quantity to compare to. - /// The tolerance value for the maximum allowed difference. - /// - /// True if the absolute difference between the two quantities, when converted to linear space, is not greater - /// than the specified tolerance. - /// - /// Thrown when no unit information is found for one of the specified enum value. - /// - /// This method converts the quantities and the tolerance to linear space before performing the comparison, an - /// operation which doesn't produce an exact value. - /// - /// It is generally advised against specifying "zero" tolerance, preferring the use of the default equality - /// comparer, which is significantly more performant. - /// - /// - private static bool EqualsAbsolute(this TQuantity quantity, TOther other, TTolerance tolerance) + private static bool EqualsNotNull(TQuantity quantity, TOther other, TQuantity tolerance) where TQuantity : ILogarithmicQuantity - where TOther : IQuantityOfType - where TTolerance : IQuantityOfType + where TOther : ILogarithmicQuantity { UnitKey quantityUnit = quantity.UnitKey; #if NET diff --git a/UnitsNet/Extensions/QuantityExtensions.cs b/UnitsNet/Extensions/QuantityExtensions.cs index 41f2ace803..c481121c8d 100644 --- a/UnitsNet/Extensions/QuantityExtensions.cs +++ b/UnitsNet/Extensions/QuantityExtensions.cs @@ -10,14 +10,31 @@ namespace UnitsNet; /// public static class QuantityExtensions { + /// + /// + /// + /// + /// + /// + /// + public static bool Equals(this IQuantity quantity, IQuantity? other, IQuantity tolerance) + { + if (quantity is null) throw new ArgumentNullException(nameof(quantity)); + if (tolerance is null) throw new ArgumentNullException(nameof(tolerance), "Tolerance cannot be null. Use a zero quantity instead."); + if (other is null) return false; + + // TODO Delegate to implementations in LinearQuantityExtensions, AffineQuantityExtensions, LogdecimalQuantityExtensions, etc. Several tests in QuantityExtensionsTests break on this default implementation. + UnitKey quantityUnit = quantity.UnitKey; + return Comparison.EqualsAbsolute(quantity.Value, other.GetValue(quantityUnit), tolerance.GetValue(quantityUnit)); + } + /// /// This should be using UnitConverter.Default.ConvertValue(quantity, toUnit) - internal static double GetValue(this TQuantity quantity, UnitKey toUnit) - where TQuantity : IQuantity + internal static double GetValue(this IQuantity quantity, UnitKey toUnit) { return quantity.As(toUnit); } - + /// /// Returns the string representation of the specified quantity using the provided format provider. /// @@ -71,7 +88,7 @@ internal static TQuantity ArithmeticMean(this IEnumerable { throw new ArgumentNullException(nameof(quantities)); } - + using IEnumerator enumerator = quantities.GetEnumerator(); if (!enumerator.MoveNext()) { @@ -117,7 +134,7 @@ internal static TQuantity ArithmeticMean(this IEnumerable enumerator = quantities.GetEnumerator(); if (!enumerator.MoveNext()) {