Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions UnitsNet.Tests/AffineQuantityExtensionsTest.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// 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.Numerics;
using UnitsNet.Tests.CustomQuantities;

namespace UnitsNet.Tests;
Expand Down Expand Up @@ -109,6 +110,49 @@ public void Equals_TQuantity_WithNullOther_ReturnsFalse()

Assert.False(result);
}

[Theory]
[InlineData(25.0, 25.0, 0.1, true)] // Equal values
[InlineData(25.0, 25.1, 0.1, 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_GenericAffineQuantity_ComparesWithinTolerance(double value1, double value2, double toleranceValue, bool expected)
{
var temperature1 = Temperature.FromDegreesCelsius(value1);
var temperature2 = Temperature.FromDegreesCelsius(value2);
var tolerance = TemperatureDelta.FromDegreesCelsius(toleranceValue);

Assert.Equal(expected, GenericEquals(temperature1, temperature2, tolerance));
Assert.Equal(expected, GenericEqualsIQuantity(temperature1, temperature2, tolerance));
}

[Fact]
public void Equals_GenericAffineQuantity_ThrowsArgumentOutOfRangeException_ForNegativeTolerance()
{
var temperature1 = Temperature.FromDegreesCelsius(25.0);
var temperature2 = Temperature.FromDegreesCelsius(25.0);
var negativeTolerance = TemperatureDelta.FromDegreesCelsius(-0.1);

Assert.Throws<ArgumentOutOfRangeException>(() => GenericEquals(temperature1, temperature2, negativeTolerance));
Assert.Throws<ArgumentOutOfRangeException>(() => GenericEqualsIQuantity(temperature1, temperature2, negativeTolerance));
}

// Calling Equals in a generic context binds to the generic overloads; with concrete Temperature arguments
// the compiler prefers the Temperature-specific overloads instead.
private static bool GenericEquals<TQuantity, TOffset>(TQuantity quantity, TQuantity other, TOffset tolerance)
where TQuantity : IAffineQuantity<TQuantity, TOffset>, ISubtractionOperators<TQuantity, TQuantity, TOffset>
where TOffset : IQuantityOfType<TOffset>, IAdditiveIdentity<TOffset, TOffset>
{
return quantity.Equals(other, tolerance);
}

private static bool GenericEqualsIQuantity<TQuantity, TOffset>(TQuantity quantity, IQuantity other, TOffset tolerance)
where TQuantity : IAffineQuantity<TQuantity, TOffset>, ISubtractionOperators<TQuantity, TQuantity, TOffset>
where TOffset : IQuantityOfType<TOffset>, IAdditiveIdentity<TOffset, TOffset>
{
return quantity.Equals(other, tolerance);
}
#endif

[Fact]
Expand Down
17 changes: 17 additions & 0 deletions UnitsNet.Tests/CustomCode/IQuantityTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.

using System.Numerics;
using UnitsNet.Tests.CustomQuantities;

namespace UnitsNet.Tests;

Expand Down Expand Up @@ -265,6 +266,22 @@ public void GetQuantityInfo_Typed_ReturnsRegisteredQuantityInfo()
Assert.Same(Mass.Info, info);
}

[Fact]
public void QuantityInfo_IQuantityOfTypeReference_ReturnsQuantityInfo()
{
// Part of the netstandard2.0 API, so it must also exist on .NET for libraries compiled against netstandard2.0.
Assert.Same(Mass.Info, GetQuantityInfo(new Mass(1.0, MassUnit.Kilogram)));
Assert.Same(HowMuch.Info, GetQuantityInfo(new HowMuch(1.0, HowMuchUnit.Some)));

static IQuantityInstanceInfo<TQuantity> GetQuantityInfo<TQuantity>(TQuantity quantity)
where TQuantity : IQuantityOfType<TQuantity>
{
#pragma warning disable CS0618 // Type or member is obsolete
return quantity.QuantityInfo;
#pragma warning restore CS0618
}
}

#if NET
[Fact]
public void StaticAbstract_Info_ReturnsSameAsTypedInfo()
Expand Down
66 changes: 66 additions & 0 deletions UnitsNet/CompatibilitySuppressions.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://learn.microsoft.com/dotnet/fundamentals/package-validation/diagnostic-ids -->
<!--
Every public member available on netstandard2.0 must also exist on .NET, since a library compiled against
netstandard2.0 may run in an app that loads one of the .NET target frameworks.

The suppressions below are the intended exceptions: static abstract interface members and generic math
constraints, which require .NET 7 or later and cannot exist on netstandard2.0. Types implementing these
interfaces must therefore be compiled for .NET to run on .NET.
-->
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:UnitsNet.IQuantity`2.From(UnitsNet.QuantityValue,`1)</Target>
<Left>lib/netstandard2.0/UnitsNet.dll</Left>
<Right>lib/net8.0/UnitsNet.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:UnitsNet.IQuantityOfType`1.Create(UnitsNet.QuantityValue,UnitsNet.UnitKey)</Target>
<Left>lib/netstandard2.0/UnitsNet.dll</Left>
<Right>lib/net8.0/UnitsNet.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>P:UnitsNet.IAffineQuantity`2.Zero</Target>
<Left>lib/netstandard2.0/UnitsNet.dll</Left>
<Right>lib/net8.0/UnitsNet.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>P:UnitsNet.ILinearQuantity`1.Zero</Target>
<Left>lib/netstandard2.0/UnitsNet.dll</Left>
<Right>lib/net8.0/UnitsNet.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>P:UnitsNet.ILogarithmicQuantity`1.Zero</Target>
<Left>lib/netstandard2.0/UnitsNet.dll</Left>
<Right>lib/net8.0/UnitsNet.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>P:UnitsNet.IQuantity`2.Info</Target>
<Left>lib/netstandard2.0/UnitsNet.dll</Left>
<Right>lib/net8.0/UnitsNet.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>P:UnitsNet.IQuantityOfType`1.Info</Target>
<Left>lib/netstandard2.0/UnitsNet.dll</Left>
<Right>lib/net8.0/UnitsNet.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0021</DiagnosticId>
<Target>T:UnitsNet.IAffineQuantity`2``1:T:System.Numerics.IAdditiveIdentity{`1,`1}</Target>
<Left>lib/netstandard2.0/UnitsNet.dll</Left>
<Right>lib/net8.0/UnitsNet.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0021</DiagnosticId>
<Target>T:UnitsNet.IAffineQuantity`3``2:T:System.Numerics.IAdditiveIdentity{`2,`2}</Target>
<Left>lib/netstandard2.0/UnitsNet.dll</Left>
<Right>lib/net8.0/UnitsNet.dll</Right>
</Suppression>
</Suppressions>
4 changes: 2 additions & 2 deletions UnitsNet/Extensions/AffineQuantityExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ private static bool EqualsAbsolute<TQuantity, TOffset>(this TQuantity quantity,
TOffset difference = quantity - other;
return QuantityValue.Abs(difference.Value) <= tolerance.GetValue(difference.UnitKey);
}
#else
#endif

/// <summary>
/// <para>
/// Compare equality to <paramref name="other" /> given a <paramref name="tolerance" /> for the maximum allowed +/-
Expand Down Expand Up @@ -109,7 +110,6 @@ public static bool Equals(this Temperature quantity, IQuantity? other, Temperatu
{
return other is Temperature otherInstance && quantity.Equals(otherInstance, tolerance);
}
#endif

/// <summary>
/// Calculates the average of a collection of <see cref="Temperature" /> values.
Expand Down
11 changes: 9 additions & 2 deletions UnitsNet/IQuantity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,13 @@ public interface IQuantityOfType<out TQuantity> : IQuantity
/// <param name="unit">The unit of the quantity.</param>
/// <returns>An instance of the quantity with the specified value and unit.</returns>
public static abstract TQuantity Create(QuantityValue value, UnitKey unit);
#else
#endif

/// <inheritdoc cref="IQuantity.QuantityInfo"/>
new IQuantityInstanceInfo<TQuantity> QuantityInfo { get; }
#if NET
[Obsolete("Kept for back-compat with netstandard2.0. On .NET 5+, use the static TSelf.Info property or the GetQuantityInfo() extension method.")]
#endif
new IQuantityInstanceInfo<TQuantity> QuantityInfo { get; }
}

/// <summary>
Expand Down Expand Up @@ -146,6 +149,10 @@ public interface IQuantity<TSelf, TUnitType> : IQuantityOfType<TSelf>, IQuantity

static QuantityInfo IQuantityOfType<TSelf>.Info => TSelf.Info;

#pragma warning disable CS0618 // Type or member is obsolete
IQuantityInstanceInfo<TSelf> IQuantityOfType<TSelf>.QuantityInfo => TSelf.Info;
#pragma warning restore CS0618

#pragma warning disable CS0618 // Type or member is obsolete
QuantityInfo<TUnitType> IQuantity<TUnitType>.QuantityInfo
{
Expand Down
14 changes: 2 additions & 12 deletions UnitsNet/IQuantityInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,7 @@ namespace UnitsNet;
/// <remarks>
/// Typically you obtain this by looking it up via <see cref="IQuantity.QuantityInfo" />.
/// </remarks>
#if NETSTANDARD2_0
public
#else
internal
#endif
interface IQuantityInfo
public interface IQuantityInfo
{
/// <summary>
/// Quantity name, such as "Length" or "Mass".
Expand Down Expand Up @@ -111,12 +106,7 @@ interface IQuantityInfo
/// This is a specialization of <see cref="IQuantityInfo" /> that is used (internally) for constraining certain
/// methods, without having to include the unit type as additional generic parameter.
/// </remarks>
#if NETSTANDARD2_0
public
#else
internal
#endif
interface IQuantityInstanceInfo<out TQuantity> : IQuantityInfo
public interface IQuantityInstanceInfo<out TQuantity> : IQuantityInfo
where TQuantity : IQuantity
{
/// <inheritdoc cref="IQuantityInfo.Zero" />
Expand Down
2 changes: 2 additions & 0 deletions UnitsNet/UnitsNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
<PackageTags>unit units quantity quantities measurement si metric imperial abbreviation abbreviations convert conversion parse immutable</PackageTags>
<PackageReadmeFile>README.md</PackageReadmeFile>
<IsAotCompatible Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))">true</IsAotCompatible>
<!-- Validates that the public API is compatible across target frameworks, since an app may load a different target framework than a library compiled against this package -->
<EnablePackageValidation>true</EnablePackageValidation>
</PropertyGroup>

<!-- Assembly and msbuild properties -->
Expand Down
Loading