diff --git a/Samples/MvvmSample.Wpf/MvvmSample.Wpf/Converters/UnitToStringConverter.cs b/Samples/MvvmSample.Wpf/MvvmSample.Wpf/Converters/UnitToStringConverter.cs
index f7f2806f73..7292c45de3 100644
--- a/Samples/MvvmSample.Wpf/MvvmSample.Wpf/Converters/UnitToStringConverter.cs
+++ b/Samples/MvvmSample.Wpf/MvvmSample.Wpf/Converters/UnitToStringConverter.cs
@@ -31,7 +31,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn
if (!(value is IQuantity quantity))
throw new ArgumentException("Expected value of type UnitsNet.IQuantity.", nameof(value));
- Enum unitEnumValue = _settings.GetDefaultUnit(quantity.QuantityInfo.UnitType);
+ Enum unitEnumValue = _settings.GetDefaultUnit(quantity.GetQuantityInfo().UnitType);
int significantDigits = _settings.SignificantDigits;
IQuantity quantityInUnit = quantity.ToUnit(unitEnumValue);
diff --git a/UnitsNet.Benchmark/Conversions/ToUnit/QuantityConversionBenchmarks.cs b/UnitsNet.Benchmark/Conversions/ToUnit/QuantityConversionBenchmarks.cs
index 926ca0f2d3..08c304fc59 100644
--- a/UnitsNet.Benchmark/Conversions/ToUnit/QuantityConversionBenchmarks.cs
+++ b/UnitsNet.Benchmark/Conversions/ToUnit/QuantityConversionBenchmarks.cs
@@ -19,7 +19,7 @@ public double ConvertOnce()
double result = 0;
foreach (IQuantity quantity in Quantities)
{
- foreach (UnitInfo unitInfo in quantity.QuantityInfo.UnitInfos)
+ foreach (UnitInfo unitInfo in quantity.GetQuantityInfo().UnitInfos)
{
result = quantity.As(unitInfo.Value);
}
diff --git a/UnitsNet.Serialization.JsonNet/AbbreviatedUnitsConverter.cs b/UnitsNet.Serialization.JsonNet/AbbreviatedUnitsConverter.cs
index 10fc5b9b19..1514d89d0f 100644
--- a/UnitsNet.Serialization.JsonNet/AbbreviatedUnitsConverter.cs
+++ b/UnitsNet.Serialization.JsonNet/AbbreviatedUnitsConverter.cs
@@ -99,7 +99,9 @@ public override void WriteJson(JsonWriter writer, IQuantity? quantity, JsonSeria
/// The string representation associated with the given quantity
protected string GetQuantityType(IQuantity quantity)
{
+#pragma warning disable CS0618 // IQuantity.QuantityInfo: serialization must work for custom quantities not registered in UnitsNetSetup.Default.
return _quantities[quantity.QuantityInfo.Name].Name;
+#pragma warning restore CS0618
}
///
diff --git a/UnitsNet.Serialization.JsonNet/UnitsNetBaseJsonConverter.cs b/UnitsNet.Serialization.JsonNet/UnitsNetBaseJsonConverter.cs
index 73f4cce110..d4f6053579 100644
--- a/UnitsNet.Serialization.JsonNet/UnitsNetBaseJsonConverter.cs
+++ b/UnitsNet.Serialization.JsonNet/UnitsNetBaseJsonConverter.cs
@@ -164,7 +164,9 @@ protected ValueUnit ConvertIQuantity(IQuantity quantity)
{
quantity = quantity ?? throw new ArgumentNullException(nameof(quantity));
+#pragma warning disable CS0618 // IQuantity.QuantityInfo: serialization must work for custom quantities not registered in UnitsNetSetup.Default.
return new ValueUnit {Value = (double)quantity.Value, Unit = $"{quantity.QuantityInfo.UnitType.Name}.{quantity.Unit}"};
+#pragma warning restore CS0618
}
///
diff --git a/UnitsNet.Tests/CustomCode/IQuantityTests.cs b/UnitsNet.Tests/CustomCode/IQuantityTests.cs
index 2aee75a27d..db4b6936f6 100644
--- a/UnitsNet.Tests/CustomCode/IQuantityTests.cs
+++ b/UnitsNet.Tests/CustomCode/IQuantityTests.cs
@@ -116,6 +116,58 @@ public void GetUnitInfo_MatchesUnit()
});
}
+ [Fact]
+ public void GetQuantityInfo_NonGeneric_ReturnsRegisteredQuantityInfo()
+ {
+ IQuantity quantity = new Mass(1.0, MassUnit.Kilogram);
+
+ QuantityInfo info = quantity.GetQuantityInfo();
+
+ Assert.Same(Mass.Info, info);
+ }
+
+ [Fact]
+ public void GetQuantityInfo_Typed_ReturnsRegisteredQuantityInfo()
+ {
+ IQuantity quantity = new Mass(1.0, MassUnit.Kilogram);
+
+ QuantityInfo info = quantity.GetQuantityInfo();
+
+ Assert.Same(Mass.Info, info);
+ }
+
+ [Fact]
+ public void StaticAbstract_Info_ReturnsSameAsTypedInfo()
+ {
+ // Calls IQuantity.Info via the static abstract member.
+ QuantityInfo typedInfo = Mass.Info;
+ QuantityInfo viaStaticAbstract = StaticAbstractAccess();
+
+ Assert.Same(typedInfo, viaStaticAbstract);
+
+ static QuantityInfo StaticAbstractAccess()
+ where TSelf : IQuantity
+ where TUnit : struct, Enum
+ {
+ return TSelf.Info;
+ }
+ }
+
+ [Fact]
+ public void StaticAbstract_Info_NonGeneric_ReturnsSameAsTypedInfo()
+ {
+ // Calls IQuantityOfType.Info via the static abstract member.
+ QuantityInfo info = StaticAbstractAccess();
+
+ Assert.Same((QuantityInfo)Mass.Info, info);
+
+ static QuantityInfo StaticAbstractAccess()
+ where TQuantity : IQuantityOfType
+ {
+ return TQuantity.Info;
+ }
+ }
+
[Fact]
public void ToUnit_UnitSystem_ThrowsArgumentExceptionIfNotSupported()
{
diff --git a/UnitsNet.Tests/CustomQuantities/HowMuch.cs b/UnitsNet.Tests/CustomQuantities/HowMuch.cs
index 7a59f20a8d..36cb65f121 100644
--- a/UnitsNet.Tests/CustomQuantities/HowMuch.cs
+++ b/UnitsNet.Tests/CustomQuantities/HowMuch.cs
@@ -31,7 +31,7 @@ public double As(HowMuchUnit unit)
#region IQuantity
- public static readonly QuantityInfo Info = new(
+ public static QuantityInfo Info { get; } = new(
nameof(HowMuch),
HowMuchUnit.Some,
new UnitDefinition[]
diff --git a/UnitsNet/Extensions/LinearQuantityExtensions.cs b/UnitsNet/Extensions/LinearQuantityExtensions.cs
index d6183625c9..f56448b8fd 100644
--- a/UnitsNet/Extensions/LinearQuantityExtensions.cs
+++ b/UnitsNet/Extensions/LinearQuantityExtensions.cs
@@ -162,7 +162,11 @@ public static TQuantity Sum(this IEnumerable quanti
resultValue += enumerator.Current!.GetValue(unitKey);
}
+#if NET
+ return TQuantity.From(resultValue, unit);
+#else
return firstQuantity.QuantityInfo.From(resultValue, unit);
+#endif
}
///
diff --git a/UnitsNet/Extensions/LogarithmicQuantityExtensions.cs b/UnitsNet/Extensions/LogarithmicQuantityExtensions.cs
index 7f28720e05..f79f8874e8 100644
--- a/UnitsNet/Extensions/LogarithmicQuantityExtensions.cs
+++ b/UnitsNet/Extensions/LogarithmicQuantityExtensions.cs
@@ -203,7 +203,11 @@ public static TQuantity Sum(this IEnumerable quanti
sumInLinearSpace += enumerator.Current!.GetValue(unitKey).ToLinearSpace(logarithmicScalingFactor);
}
+#if NET
+ return TQuantity.From(sumInLinearSpace.ToLogSpace(logarithmicScalingFactor), targetUnit);
+#else
return firstQuantity.QuantityInfo.From(sumInLinearSpace.ToLogSpace(logarithmicScalingFactor), targetUnit);
+#endif
}
///
@@ -342,7 +346,11 @@ public static TQuantity ArithmeticMean(this IEnumerable
@@ -473,7 +481,11 @@ public static TQuantity GeometricMean(this IEnumerable());
+#else
return firstQuantity.QuantityInfo.From(geometricMean, unitKey.ToUnit());
+#endif
}
///
diff --git a/UnitsNet/Extensions/QuantityExtensions.cs b/UnitsNet/Extensions/QuantityExtensions.cs
index 229907569d..2cedba1cdc 100644
--- a/UnitsNet/Extensions/QuantityExtensions.cs
+++ b/UnitsNet/Extensions/QuantityExtensions.cs
@@ -11,6 +11,30 @@ namespace UnitsNet;
///
public static class QuantityExtensions
{
+ ///
+ /// Gets the for the given quantity instance, looked up via
+ /// .
+ ///
+ ///
+ /// Use the static TSelf.Info directly when you have a typed quantity reference for the best performance.
+ /// This extension is convenient when working with an reference where the concrete
+ /// type is not known at compile time.
+ ///
+ /// The quantity instance.
+ /// The registered in for the quantity's runtime type.
+ public static QuantityInfo GetQuantityInfo(this IQuantity quantity)
+ {
+ return UnitsNetSetup.Default.Quantities.GetQuantityInfo(quantity.GetType());
+ }
+
+ ///
+ /// The unit enum type of the quantity.
+ public static QuantityInfo GetQuantityInfo(this IQuantity quantity)
+ where TUnit : struct, Enum
+ {
+ return (QuantityInfo)UnitsNetSetup.Default.Quantities.GetQuantityInfo(quantity.GetType());
+ }
+
///
/// Gets the for the unit this quantity was constructed with.
///
@@ -24,7 +48,7 @@ public static class QuantityExtensions
/// The for the quantity's unit.
public static UnitInfo GetUnitInfo(this IQuantity quantity)
{
- return quantity.QuantityInfo[quantity.UnitKey];
+ return quantity.GetQuantityInfo()[quantity.UnitKey];
}
///
@@ -44,7 +68,11 @@ public static UnitInfo GetUnitInfo(this IQua
where TQuantity : IQuantity
where TUnit : struct, Enum
{
+#if NET
+ return TQuantity.Info[quantity.Unit];
+#else
return quantity.QuantityInfo[quantity.Unit];
+#endif
}
///
@@ -72,7 +100,11 @@ internal static double GetValue(this TQuantity quantity, UnitKey toUn
public static double As(this TQuantity quantity, UnitSystem unitSystem)
where TQuantity : IQuantity
{
+#if NET
+ return quantity.GetValue(quantity.GetQuantityInfo().GetDefaultUnit(unitSystem).UnitKey);
+#else
return quantity.GetValue(quantity.QuantityInfo.GetDefaultUnit(unitSystem).UnitKey);
+#endif
}
///
@@ -100,7 +132,7 @@ public static TQuantity ToUnit(this TQuantity quantity, UnitSystem un
where TQuantity : IQuantityOfType
{
#if NET
- QuantityInfo quantityInfo = quantity.QuantityInfo;
+ QuantityInfo quantityInfo = TQuantity.Info;
UnitKey unitKey = quantityInfo.GetDefaultUnit(unitSystem).UnitKey;
return TQuantity.Create(quantity.As(unitKey), unitKey);
#else
@@ -277,6 +309,10 @@ internal static TQuantity ArithmeticMean(this IEnumerable
/// Information about the quantity type, such as unit values and names.
///
+ ///
+ /// Kept for back-compat with netstandard2.0. On .NET 5+, prefer the static TSelf.Info
+ /// property or the GetQuantityInfo() extension method on .
+ ///
+#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
QuantityInfo QuantityInfo { get; }
///
@@ -82,6 +89,9 @@ public interface IQuantity : IQuantity
new TUnitType Unit { 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 QuantityInfo QuantityInfo { get; }
///
@@ -96,10 +106,12 @@ public interface IQuantity : IQuantity
#region Implementation of IQuantity
+#pragma warning disable CS0618 // Type or member is obsolete
QuantityInfo IQuantity.QuantityInfo
{
get => QuantityInfo;
}
+#pragma warning restore CS0618
Enum IQuantity.Unit
{
@@ -121,6 +133,16 @@ public interface IQuantityOfType : IQuantity
where TQuantity : IQuantity
{
#if NET
+ ///
+ /// The static for this quantity type.
+ ///
+ ///
+ /// Implemented by every quantity as a public static Info property. Prefer this and the
+ /// extension method over the
+ /// obsolete instance property.
+ ///
+ public static abstract QuantityInfo Info { get; }
+
///
/// Creates an instance of the quantity from a specified value and unit.
///
@@ -144,9 +166,15 @@ public interface IQuantity : IQuantityOfType, IQuantity
where TUnitType : struct, Enum
{
///
+#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 QuantityInfo QuantityInfo { get; }
#if NET
+ ///
+ public new static abstract QuantityInfo Info { get; }
+
///
/// Creates an instance of the quantity from a specified value and unit.
///
@@ -157,10 +185,14 @@ public interface IQuantity : IQuantityOfType, IQuantity
static TSelf IQuantityOfType.Create(double value, UnitKey unit) => TSelf.From(value, unit.ToUnit());
+ static QuantityInfo IQuantityOfType.Info => TSelf.Info;
+
+#pragma warning disable CS0618 // Type or member is obsolete
QuantityInfo IQuantity.QuantityInfo
{
get => QuantityInfo;
}
+#pragma warning restore CS0618
IQuantity IQuantity.ToUnit(TUnitType unit)
{
diff --git a/UnitsNet/QuantityDisplay.cs b/UnitsNet/QuantityDisplay.cs
index 166afc9544..4395ad7386 100644
--- a/UnitsNet/QuantityDisplay.cs
+++ b/UnitsNet/QuantityDisplay.cs
@@ -32,7 +32,9 @@ internal readonly struct AbbreviationDisplay
public AbbreviationDisplay(IQuantity quantity)
{
_quantity = quantity;
+#pragma warning disable CS0618 // IQuantity.QuantityInfo: debug proxy must work for custom quantities not registered in UnitsNetSetup.Default.
QuantityInfo quantityQuantityInfo = quantity.QuantityInfo;
+#pragma warning restore CS0618
IQuantity baseQuantity = quantity.ToUnit(quantityQuantityInfo.BaseUnitInfo.Value);
Conversions = quantityQuantityInfo.UnitInfos.Select(x => new ConvertedQuantity(baseQuantity, x)).ToArray();
}
@@ -70,8 +72,11 @@ internal readonly struct UnitDisplay
public UnitDisplay(IQuantity quantity)
{
Unit = quantity.Unit;
- IQuantity baseQuantity = quantity.ToUnit(quantity.QuantityInfo.BaseUnitInfo.Value);
- Conversions = quantity.QuantityInfo.UnitInfos.Select(x => new ConvertedQuantity(baseQuantity, x.Value)).ToArray();
+#pragma warning disable CS0618 // IQuantity.QuantityInfo: debug proxy must work for custom quantities not registered in UnitsNetSetup.Default.
+ QuantityInfo info = quantity.QuantityInfo;
+#pragma warning restore CS0618
+ IQuantity baseQuantity = quantity.ToUnit(info.BaseUnitInfo.Value);
+ Conversions = info.UnitInfos.Select(x => new ConvertedQuantity(baseQuantity, x.Value)).ToArray();
}
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
@@ -110,7 +115,9 @@ internal readonly struct QuantityConvertor
public QuantityConvertor(IQuantity quantity)
{
QuantityToString = new StringFormatsDisplay(quantity);
+#pragma warning disable CS0618 // IQuantity.QuantityInfo: debug proxy must work for custom quantities not registered in UnitsNetSetup.Default.
QuantityInfo quantityQuantityInfo = quantity.QuantityInfo;
+#pragma warning restore CS0618
IQuantity baseQuantity = quantity.ToUnit(quantityQuantityInfo.BaseUnitInfo.Value);
QuantityToUnit = quantityQuantityInfo.UnitInfos.Select(x => new ConvertedQuantity(baseQuantity.ToUnit(x.Value), x)).ToArray();
}
diff --git a/UnitsNet/QuantityTypeConverter.cs b/UnitsNet/QuantityTypeConverter.cs
index ad4350abef..dcbed81dfa 100644
--- a/UnitsNet/QuantityTypeConverter.cs
+++ b/UnitsNet/QuantityTypeConverter.cs
@@ -153,8 +153,10 @@ private static TAttribute? GetAttribute<
// Ensure the attribute's unit is compatible with this converter's quantity.
if (attribute?.UnitType != null)
{
+#pragma warning disable CS0618 // IQuantity.QuantityInfo is obsolete on .NET 5+; use it here so consumers can author custom quantities (e.g. HowMuch in tests) without registering them in UnitsNetSetup.Default.
string converterQuantityName = default(TQuantity).QuantityInfo.Name;
string attributeQuantityName = Quantity.From(1, attribute.UnitType).QuantityInfo.Name;
+#pragma warning restore CS0618
if (converterQuantityName != attributeQuantityName)
{
throw new ArgumentException($"The {attribute.GetType()}'s UnitType [{attribute.UnitType}] is not compatible with the converter's quantity [{converterQuantityName}].");