diff --git a/CodeGen/Generators/UnitsNetGen/QuantityGenerator.cs b/CodeGen/Generators/UnitsNetGen/QuantityGenerator.cs
index b9a6039db9..b9d609739c 100644
--- a/CodeGen/Generators/UnitsNetGen/QuantityGenerator.cs
+++ b/CodeGen/Generators/UnitsNetGen/QuantityGenerator.cs
@@ -5,6 +5,7 @@
using System.Linq;
using CodeGen.Helpers;
using CodeGen.JsonTypes;
+using static System.Runtime.InteropServices.JavaScript.JSType;
namespace CodeGen.Generators.UnitsNetGen
{
@@ -34,13 +35,10 @@ public string Generate()
{
Writer.WL(GeneratedFileHeader);
Writer.WL(@"
-using System;
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
+
using System.Globalization;
-using System.Linq;
+using System.Resources;
using System.Runtime.Serialization;
-using UnitsNet.Units;
#if NET
using System.Numerics;
#endif
@@ -122,6 +120,7 @@ namespace UnitsNet
[DataMember(Name = ""Unit"", Order = 2)]
private readonly {_unitEnumName}? _unit;
");
+ GenerateQuantityInfo();
GenerateStaticConstructor();
GenerateInstanceConstructors();
GenerateStaticProperties();
@@ -141,36 +140,86 @@ namespace UnitsNet
}}");
return Writer.ToString();
}
-
- private void GenerateStaticConstructor()
+
+ private void GenerateQuantityInfo()
{
+ var quantityInfoClassName = $"{_quantity.Name}Info";
BaseDimensions baseDimensions = _quantity.BaseDimensions;
+ var createDimensionsExpression = _isDimensionless
+ ? "BaseDimensions.Dimensionless"
+ : $"new BaseDimensions({baseDimensions.L}, {baseDimensions.M}, {baseDimensions.T}, {baseDimensions.I}, {baseDimensions.Θ}, {baseDimensions.N}, {baseDimensions.J})";
+
Writer.WL($@"
- static {_quantity.Name}()
+ ///
+ /// Provides detailed information about the quantity, including its name, base unit, unit mappings, base dimensions, and conversion functions.
+ ///
+ public sealed class {quantityInfoClassName}: QuantityInfo<{_quantity.Name}, {_unitEnumName}>
{{");
- Writer.WL(_isDimensionless ? $@"
- BaseDimensions = BaseDimensions.Dimensionless;" : $@"
- BaseDimensions = new BaseDimensions({baseDimensions.L}, {baseDimensions.M}, {baseDimensions.T}, {baseDimensions.I}, {baseDimensions.Θ}, {baseDimensions.N}, {baseDimensions.J});");
-
Writer.WL($@"
- BaseUnit = {_unitEnumName}.{_quantity.BaseUnit};
- Units = Enum.GetValues(typeof({_unitEnumName})).Cast<{_unitEnumName}>().ToArray();
- Zero = new {_quantity.Name}(0, BaseUnit);
- Info = new QuantityInfo<{_unitEnumName}>(""{_quantity.Name}"",
- new UnitInfo<{_unitEnumName}>[]
- {{");
+ ///
+ public {quantityInfoClassName}(string name, {_unitEnumName} baseUnit, IEnumerable> unitMappings, {_quantity.Name} zero, BaseDimensions baseDimensions,
+ QuantityFromDelegate<{_quantity.Name}, {_unitEnumName}> fromDelegate, ResourceManager? unitAbbreviations)
+ : base(name, baseUnit, unitMappings, zero, baseDimensions, fromDelegate, unitAbbreviations)
+ {{
+ }}
+
+ ///
+ public {quantityInfoClassName}(string name, {_unitEnumName} baseUnit, IEnumerable> unitMappings, {_quantity.Name} zero, BaseDimensions baseDimensions)
+ : this(name, baseUnit, unitMappings, zero, baseDimensions, {_quantity.Name}.From, new ResourceManager(""UnitsNet.GeneratedCode.Resources.{_quantity.Name}"", typeof({_quantity.Name}).Assembly))
+ {{
+ }}
+
+ ///
+ /// Creates a new instance of the class with the default settings for the {_quantity.Name} quantity.
+ ///
+ /// A new instance of the class with the default settings.
+ public static {quantityInfoClassName} CreateDefault()
+ {{
+ return new {quantityInfoClassName}(nameof({_quantity.Name}), DefaultBaseUnit, GetDefaultMappings(), new {_quantity.Name}(0, DefaultBaseUnit), DefaultBaseDimensions);
+ }}
+
+ ///
+ /// Creates a new instance of the class with the default settings for the {_quantity.Name} quantity and a callback for customizing the default unit mappings.
+ ///
+ ///
+ /// A callback function for customizing the default unit mappings.
+ ///
+ ///
+ /// A new instance of the class with the default settings.
+ ///
+ public static {quantityInfoClassName} CreateDefault(Func>, IEnumerable>> customizeUnits)
+ {{
+ return new {quantityInfoClassName}(nameof({_quantity.Name}), DefaultBaseUnit, customizeUnits(GetDefaultMappings()), new {_quantity.Name}(0, DefaultBaseUnit), DefaultBaseDimensions);
+ }}
+ ///
+ /// The for is {_quantity.BaseDimensions}.
+ ///
+ public static BaseDimensions DefaultBaseDimensions {{ get; }} = {createDimensionsExpression};
+
+ ///
+ /// The default base unit of {_quantity.Name} is {_baseUnit.SingularName}. All conversions, as defined in the , go via this value.
+ ///
+ public static {_unitEnumName} DefaultBaseUnit {{ get; }} = {_unitEnumName}.{_baseUnit.SingularName};
+
+ ///
+ /// Retrieves the default mappings for .
+ ///
+ /// An of representing the default unit mappings for {_quantity.Name}.
+ public static IEnumerable> GetDefaultMappings()
+ {{");
+
foreach (Unit unit in _quantity.Units)
{
BaseUnits? baseUnits = unit.BaseUnits;
+ string baseUnitsFormat;
if (baseUnits == null)
{
- Writer.WL($@"
- new UnitInfo<{_unitEnumName}>({_unitEnumName}.{unit.SingularName}, ""{unit.PluralName}"", BaseUnits.Undefined, ""{_quantity.Name}""),");
+ baseUnitsFormat = "BaseUnits.Undefined";
}
else
{
- var baseUnitsCtorArgs = string.Join(", ",
+ baseUnitsFormat = $"new BaseUnits({string.Join(", ",
new[]
{
baseUnits.L != null ? $"length: LengthUnit.{baseUnits.L}" : null,
@@ -180,17 +229,26 @@ private void GenerateStaticConstructor()
baseUnits.Θ != null ? $"temperature: TemperatureUnit.{baseUnits.Θ}" : null,
baseUnits.N != null ? $"amount: AmountOfSubstanceUnit.{baseUnits.N}" : null,
baseUnits.J != null ? $"luminousIntensity: LuminousIntensityUnit.{baseUnits.J}" : null
- }.Where(str => str != null));
-
- Writer.WL($@"
- new UnitInfo<{_unitEnumName}>({_unitEnumName}.{unit.SingularName}, ""{unit.PluralName}"", new BaseUnits({baseUnitsCtorArgs}), ""{_quantity.Name}""),");
+ }.Where(str => str != null))})";
}
+
+ Writer.WL($@"
+ yield return new ({_unitEnumName}.{unit.SingularName}, ""{unit.SingularName}"", ""{unit.PluralName}"", {baseUnitsFormat});");
}
Writer.WL($@"
- }},
- BaseUnit, Zero, BaseDimensions);
-
+ }}
+ }}
+");
+ }
+
+ private void GenerateStaticConstructor()
+ {
+ Writer.WL($@"
+ static {_quantity.Name}()
+ {{");
+ Writer.WL($@"
+ Info = {_quantity.Name}Info.CreateDefault();
DefaultConversionFunctions = new UnitConverter();
RegisterDefaultConversions(DefaultConversionFunctions);
}}
@@ -244,27 +302,27 @@ private void GenerateStaticProperties()
public static UnitConverter DefaultConversionFunctions {{ get; }}
///
- public static QuantityInfo<{_unitEnumName}> Info {{ get; }}
+ public static QuantityInfo<{_quantity.Name}, {_unitEnumName}> Info {{ get; }}
///
/// The of this quantity.
///
- public static BaseDimensions BaseDimensions {{ get; }}
+ public static BaseDimensions BaseDimensions => Info.BaseDimensions;
///
/// The base unit of {_quantity.Name}, which is {_quantity.BaseUnit}. All conversions go via this value.
///
- public static {_unitEnumName} BaseUnit {{ get; }}
+ public static {_unitEnumName} BaseUnit => Info.BaseUnitInfo.Value;
///
/// All units of measurement for the {_quantity.Name} quantity.
///
- public static {_unitEnumName}[] Units {{ get; }}
+ public static IReadOnlyCollection<{_unitEnumName}> Units => Info.Units;
///
/// Gets an instance of this quantity with a value of 0 in the base unit {_quantity.BaseUnit}.
///
- public static {_quantity.Name} Zero {{ get; }}
+ public static {_quantity.Name} Zero => Info.Zero;
");
if (_quantity.GenerateArithmetic)
@@ -294,7 +352,7 @@ private void GenerateProperties()
public {_unitEnumName} Unit => _unit.GetValueOrDefault(BaseUnit);
///
- public QuantityInfo<{_unitEnumName}> QuantityInfo => Info;
+ public QuantityInfo<{_quantity.Name}, {_unitEnumName}> QuantityInfo => Info;
///
/// The of this quantity.
@@ -312,6 +370,9 @@ private void GenerateProperties()
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
QuantityInfo IQuantity.QuantityInfo => Info;
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ QuantityInfo<{_unitEnumName}> IQuantity<{_unitEnumName}>.QuantityInfo => Info;
+
#endregion
#endregion
diff --git a/CodeGen/Generators/UnitsNetGen/StaticQuantityGenerator.cs b/CodeGen/Generators/UnitsNetGen/StaticQuantityGenerator.cs
index 69443fa2d5..04cb812d54 100644
--- a/CodeGen/Generators/UnitsNetGen/StaticQuantityGenerator.cs
+++ b/CodeGen/Generators/UnitsNetGen/StaticQuantityGenerator.cs
@@ -1,5 +1,4 @@
-using CodeGen.Helpers;
-using CodeGen.JsonTypes;
+using CodeGen.JsonTypes;
namespace CodeGen.Generators.UnitsNetGen
{
@@ -16,120 +15,31 @@ public string Generate()
{
Writer.WL(GeneratedFileHeader);
Writer.WL(@"
-using System;
-using System.Globalization;
-using UnitsNet.Units;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
#nullable enable
-namespace UnitsNet
+namespace UnitsNet;
+
+///
+/// Dynamically parse or construct quantities when types are only known at runtime.
+///
+public partial class Quantity
{
///
- /// Dynamically parse or construct quantities when types are only known at runtime.
+ /// Serves as a repository for predefined quantity conversion mappings, facilitating the automatic generation and retrieval of unit conversions in the UnitsNet library.
///
- public partial class Quantity
+ internal static class Provider
{
///
- /// All QuantityInfo instances mapped by quantity name that are present in UnitsNet by default.
+ /// All QuantityInfo instances that are present in UnitsNet by default.
///
- public static readonly IDictionary ByName = new Dictionary
+ internal static IReadOnlyList DefaultQuantities => new QuantityInfo[]
{");
foreach (var quantity in _quantities)
Writer.WL($@"
- {{ ""{quantity.Name}"", {quantity.Name}.Info }},");
+ {quantity.Name}.Info,");
Writer.WL(@"
};
-
- ///
- /// Dynamically constructs a quantity of the given with the value in the quantity's base units.
- ///
- /// The of the quantity to create.
- /// The value to construct the quantity with.
- /// The created quantity.
- public static IQuantity FromQuantityInfo(QuantityInfo quantityInfo, double value)
- {
- return quantityInfo.Name switch
- {");
- foreach (var quantity in _quantities)
- {
- var quantityName = quantity.Name;
- Writer.WL($@"
- ""{quantityName}"" => {quantityName}.From(value, {quantityName}.BaseUnit),");
- }
-
- Writer.WL(@"
- _ => throw new ArgumentException($""{quantityInfo.Name} is not a supported quantity."")
- };
- }
-
- ///
- /// Try to dynamically construct a quantity.
- ///
- /// Numeric value.
- /// Unit enum value.
- /// The resulting quantity if successful, otherwise default.
- /// True if successful with assigned the value, otherwise false.
- public static bool TryFrom(double value, Enum? unit, [NotNullWhen(true)] out IQuantity? quantity)
- {
- quantity = unit switch
- {");
- foreach (var quantity in _quantities)
- {
- var quantityName = quantity.Name;
- var unitTypeName = $"{quantityName}Unit";
- var unitValue = unitTypeName.ToCamelCase();
- Writer.WL($@"
- {unitTypeName} {unitValue} => {quantityName}.From(value, {unitValue}),");
- }
-
- Writer.WL(@"
- _ => null
- };
-
- return quantity is not null;
- }
-
- ///
- /// Try to dynamically parse a quantity string representation.
- ///
- /// The format provider to use for lookup. Defaults to if null.
- /// Type of quantity, such as .
- /// Quantity string representation, such as ""1.5 kg"". Must be compatible with given quantity type.
- /// The resulting quantity if successful, otherwise default.
- /// The parsed quantity.
- public static bool TryParse(IFormatProvider? formatProvider, Type quantityType, [NotNullWhen(true)] string? quantityString, [NotNullWhen(true)] out IQuantity? quantity)
- {
- quantity = default(IQuantity);
-
- if (!typeof(IQuantity).IsAssignableFrom(quantityType))
- return false;
-
- var parser = UnitsNetSetup.Default.QuantityParser;
-
- return quantityType switch
- {");
- foreach (var quantity in _quantities)
- {
- var quantityName = quantity.Name;
- Writer.WL($@"
- Type _ when quantityType == typeof({quantityName}) => parser.TryParse<{quantityName}, {quantityName}Unit>(quantityString, formatProvider, {quantityName}.From, out quantity),");
- }
-
- Writer.WL(@"
- _ => false
- };
- }
-
- internal static IEnumerable GetQuantityTypes()
- {");
- foreach (var quantity in _quantities)
- Writer.WL($@"
- yield return typeof({quantity.Name});");
- Writer.WL(@"
- }
}
}");
return Writer.ToString();
diff --git a/UnitsNet.Benchmark/Conversions/FromString/QuantityFromStringBenchmarks.cs b/UnitsNet.Benchmark/Conversions/FromString/QuantityFromStringBenchmarks.cs
index 8abb153032..9c7b03f1d1 100644
--- a/UnitsNet.Benchmark/Conversions/FromString/QuantityFromStringBenchmarks.cs
+++ b/UnitsNet.Benchmark/Conversions/FromString/QuantityFromStringBenchmarks.cs
@@ -9,7 +9,7 @@ namespace UnitsNet.Benchmark.Conversions.FromString;
[MemoryDiagnoser]
[SimpleJob(RuntimeMoniker.Net48)]
-[SimpleJob(RuntimeMoniker.Net80)]
+[SimpleJob(RuntimeMoniker.Net90)]
public class QuantityFromStringBenchmarks
{
private static readonly CultureInfo Culture = CultureInfo.InvariantCulture;
@@ -28,20 +28,20 @@ public void PrepareMassStrings()
_quantitiesToParse = _random.GetItems(["kg", "lbs", "Mlbs"], NbAbbreviations).Select(abbreviation => $"{ValueToParse} {abbreviation}").ToArray();
}
- [GlobalSetup(Target = nameof(FromVolumeUnitAbbreviation))]
+ [GlobalSetup(Target = nameof(FromVolumeString))]
public void PrepareVolumeStrings()
{
_quantitiesToParse = _random.GetItems(["ml", "l", "cm³", "m³"], NbAbbreviations).Select(abbreviation => $"{ValueToParse} {abbreviation}").ToArray();;
}
- [GlobalSetup(Target = nameof(FromPressureUnitAbbreviation))]
- public void PreparePressureUnits()
+ [GlobalSetup(Target = nameof(FromPressureString))]
+ public void PreparePressureStrings()
{
_quantitiesToParse = _random.GetRandomAbbreviations(UnitsNetSetup.Default.UnitAbbreviations, NbAbbreviations).Select(abbreviation => $"{ValueToParse} {abbreviation}").ToArray();;
}
- [GlobalSetup(Target = nameof(FromVolumeFlowUnitAbbreviation))]
- public void PrepareVolumeFlowUnits()
+ [GlobalSetup(Target = nameof(FromVolumeFlowString))]
+ public void PrepareVolumeFlowStrings()
{
// can't have "bpm" (see Frequency)
_quantitiesToParse =
@@ -63,7 +63,7 @@ public IQuantity FromMassString()
}
[Benchmark(Baseline = false)]
- public IQuantity FromVolumeUnitAbbreviation()
+ public IQuantity FromVolumeString()
{
IQuantity quantity = null;
foreach (var quantityString in _quantitiesToParse)
@@ -75,7 +75,7 @@ public IQuantity FromVolumeUnitAbbreviation()
}
[Benchmark(Baseline = false)]
- public IQuantity FromPressureUnitAbbreviation()
+ public IQuantity FromPressureString()
{
IQuantity quantity = null;
foreach (var quantityString in _quantitiesToParse)
@@ -87,7 +87,7 @@ public IQuantity FromPressureUnitAbbreviation()
}
[Benchmark(Baseline = false)]
- public IQuantity FromVolumeFlowUnitAbbreviation()
+ public IQuantity FromVolumeFlowString()
{
IQuantity quantity = null;
foreach (var quantityString in _quantitiesToParse)
diff --git a/UnitsNet.Benchmark/Conversions/FromString/QuantityFromUnitAbbreviationBenchmarks.cs b/UnitsNet.Benchmark/Conversions/FromString/QuantityFromUnitAbbreviationBenchmarks.cs
index 9a6b3ae576..a46e137560 100644
--- a/UnitsNet.Benchmark/Conversions/FromString/QuantityFromUnitAbbreviationBenchmarks.cs
+++ b/UnitsNet.Benchmark/Conversions/FromString/QuantityFromUnitAbbreviationBenchmarks.cs
@@ -9,7 +9,7 @@ namespace UnitsNet.Benchmark.Conversions.FromString;
[MemoryDiagnoser]
[SimpleJob(RuntimeMoniker.Net48)]
-[SimpleJob(RuntimeMoniker.Net80)]
+[SimpleJob(RuntimeMoniker.Net90)]
public class QuantityFromUnitAbbreviationBenchmarks
{
private static readonly CultureInfo Culture = CultureInfo.InvariantCulture;
diff --git a/UnitsNet.Benchmark/Conversions/ToString/ToStringWithDefaultPrecisionBenchmarks.cs b/UnitsNet.Benchmark/Conversions/ToString/ToStringWithDefaultPrecisionBenchmarks.cs
index 5b1381e91f..c26521c225 100644
--- a/UnitsNet.Benchmark/Conversions/ToString/ToStringWithDefaultPrecisionBenchmarks.cs
+++ b/UnitsNet.Benchmark/Conversions/ToString/ToStringWithDefaultPrecisionBenchmarks.cs
@@ -27,13 +27,13 @@ public class ToStringWithDefaultPrecisionBenchmarks
[GlobalSetup(Target = nameof(MassToString))]
public void PrepareMassesToTest()
{
- _masses = _random.GetRandomQuantities(Value, Mass.Units, NbConversions).ToArray();
+ _masses = _random.GetRandomQuantities(Value, Mass.Units.ToArray(), NbConversions).ToArray();
}
[GlobalSetup(Target = nameof(VolumeFlowToString))]
public void PrepareVolumeFlowsToTest()
{
- _volumeFlows = _random.GetRandomQuantities(Value, VolumeFlow.Units, NbConversions).ToArray();
+ _volumeFlows = _random.GetRandomQuantities(Value, VolumeFlow.Units.ToArray(), NbConversions).ToArray();
}
[Benchmark(Baseline = true)]
diff --git a/UnitsNet.Benchmark/Conversions/ToUnit/QuantityToUnitBenchmarks.cs b/UnitsNet.Benchmark/Conversions/ToUnit/QuantityToUnitBenchmarks.cs
index 31160857f1..6ced1efc3e 100644
--- a/UnitsNet.Benchmark/Conversions/ToUnit/QuantityToUnitBenchmarks.cs
+++ b/UnitsNet.Benchmark/Conversions/ToUnit/QuantityToUnitBenchmarks.cs
@@ -2,6 +2,7 @@
// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
using System;
+using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using UnitsNet.Units;
@@ -25,13 +26,13 @@ public class QuantityToUnitBenchmarks
[GlobalSetup(Target = nameof(MassToUnit))]
public void PrepareMassConversionsToTest()
{
- _massConversions = _random.GetRandomConversions(Value, Mass.Units, NbConversions);
+ _massConversions = _random.GetRandomConversions(Value, Mass.Units.ToArray(), NbConversions);
}
[GlobalSetup(Target = nameof(VolumeFlowToUnit))]
public void PrepareVolumeFlowConversionsToTest()
{
- _volumeFlowConversions = _random.GetRandomConversions(Value, VolumeFlow.Units, NbConversions);
+ _volumeFlowConversions = _random.GetRandomConversions(Value, VolumeFlow.Units.ToArray(), NbConversions);
}
[Benchmark(Baseline = true)]
diff --git a/UnitsNet.Benchmark/Conversions/ToValue/QuantityAsBenchmarks.cs b/UnitsNet.Benchmark/Conversions/ToValue/QuantityAsBenchmarks.cs
index bbab51b9a6..0dc28a0694 100644
--- a/UnitsNet.Benchmark/Conversions/ToValue/QuantityAsBenchmarks.cs
+++ b/UnitsNet.Benchmark/Conversions/ToValue/QuantityAsBenchmarks.cs
@@ -2,6 +2,7 @@
// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.
using System;
+using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using UnitsNet.Units;
@@ -29,31 +30,31 @@ public class QuantityAsBenchmarks
[GlobalSetup(Target = nameof(MassAs))]
public void PrepareMassConversionsToTest()
{
- _massConversions = _random.GetRandomConversions(Value, Mass.Units, NbConversions);
+ _massConversions = _random.GetRandomConversions(Value, Mass.Units.ToArray(), NbConversions);
}
[GlobalSetup(Target = nameof(VolumeAs))]
public void PrepareVolumeConversionsToTest()
{
- _volumeConversions = _random.GetRandomConversions(Value, Volume.Units, NbConversions);
+ _volumeConversions = _random.GetRandomConversions(Value, Volume.Units.ToArray(), NbConversions);
}
[GlobalSetup(Target = nameof(DensityAs))]
public void PrepareDensityConversionsToTest()
{
- _densityConversions = _random.GetRandomConversions(Value, Density.Units, NbConversions);
+ _densityConversions = _random.GetRandomConversions(Value, Density.Units.ToArray(), NbConversions);
}
[GlobalSetup(Target = nameof(PressureAs))]
public void PreparePressureConversionsToTest()
{
- _pressureConversions = _random.GetRandomConversions(Value, Pressure.Units, NbConversions);
+ _pressureConversions = _random.GetRandomConversions(Value, Pressure.Units.ToArray(), NbConversions);
}
[GlobalSetup(Target = nameof(VolumeFlowAs))]
public void PrepareVolumeFlowConversionsToTest()
{
- _volumeFlowConversions = _random.GetRandomConversions(Value, VolumeFlow.Units, NbConversions);
+ _volumeFlowConversions = _random.GetRandomConversions(Value, VolumeFlow.Units.ToArray(), NbConversions);
}
[Benchmark(Baseline = true)]
diff --git a/UnitsNet.Benchmark/Initializations/QuantityInfoInitializationBenchmarks.cs b/UnitsNet.Benchmark/Initializations/QuantityInfoInitializationBenchmarks.cs
new file mode 100644
index 0000000000..11f0241673
--- /dev/null
+++ b/UnitsNet.Benchmark/Initializations/QuantityInfoInitializationBenchmarks.cs
@@ -0,0 +1,43 @@
+// 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 BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Jobs;
+
+namespace UnitsNet.Benchmark.Initializations;
+
+[MemoryDiagnoser]
+[SimpleJob(RuntimeMoniker.Net48)]
+[SimpleJob(RuntimeMoniker.Net90)]
+public class QuantityInfoInitializationBenchmarks
+{
+ [Params(1000)]
+ public int NbIterations { get; set; }
+
+ [Benchmark(Baseline = true)]
+ public void CreateDefaultMass()
+ {
+ for (var i = 0; i < NbIterations; i++)
+ {
+ var quantityInfo = Mass.MassInfo.CreateDefault();
+ }
+ }
+
+ [Benchmark]
+ public void CreateDefaultVolume()
+ {
+ for (var i = 0; i < NbIterations; i++)
+ {
+ var quantityInfo = Volume.VolumeInfo.CreateDefault();
+ }
+ }
+
+ [Benchmark]
+ public void CreateDefaultVolumeFlow()
+ {
+ for (var i = 0; i < NbIterations; i++)
+ {
+ var quantityInfo = VolumeFlow.VolumeFlowInfo.CreateDefault();
+ }
+ }
+}
diff --git a/UnitsNet.Benchmark/Initializations/UnitAbbreviationsCacheInitializationBenchmarks.cs b/UnitsNet.Benchmark/Initializations/UnitAbbreviationsCacheInitializationBenchmarks.cs
index 4ca3b7a855..ccd99f7d44 100644
--- a/UnitsNet.Benchmark/Initializations/UnitAbbreviationsCacheInitializationBenchmarks.cs
+++ b/UnitsNet.Benchmark/Initializations/UnitAbbreviationsCacheInitializationBenchmarks.cs
@@ -9,7 +9,7 @@ namespace UnitsNet.Benchmark.Initializations;
[MemoryDiagnoser]
[SimpleJob(RuntimeMoniker.Net48)]
-[SimpleJob(RuntimeMoniker.Net80)]
+[SimpleJob(RuntimeMoniker.Net90)]
public class UnitAbbreviationsCacheInitializationBenchmarks
{
[GlobalSetup]
diff --git a/UnitsNet.Benchmark/Operators/Additions/AddToTemperatureWithRandomUnitsBenchmarks.cs b/UnitsNet.Benchmark/Operators/Additions/AddToTemperatureWithRandomUnitsBenchmarks.cs
index 443da4b645..596e17a990 100644
--- a/UnitsNet.Benchmark/Operators/Additions/AddToTemperatureWithRandomUnitsBenchmarks.cs
+++ b/UnitsNet.Benchmark/Operators/Additions/AddToTemperatureWithRandomUnitsBenchmarks.cs
@@ -26,8 +26,8 @@ public class AddToTemperatureWithRandomUnitsBenchmarks
[GlobalSetup]
public void PrepareQuantities()
{
- _operands = _random.GetRandomQuantities(LeftValue, Temperature.Units, NbOperations)
- .Zip(_random.GetRandomQuantities(RightValue, TemperatureDelta.Units, NbOperations),
+ _operands = _random.GetRandomQuantities(LeftValue, Temperature.Units.ToArray(), NbOperations)
+ .Zip(_random.GetRandomQuantities(RightValue, TemperatureDelta.Units.ToArray(), NbOperations),
(left, right) => (left, right))
.ToArray();
}
diff --git a/UnitsNet.Benchmark/Operators/Additions/AddTwoMassesWithRandomUnitsBenchmarks.cs b/UnitsNet.Benchmark/Operators/Additions/AddTwoMassesWithRandomUnitsBenchmarks.cs
index 1c456fb9ac..e7a921104a 100644
--- a/UnitsNet.Benchmark/Operators/Additions/AddTwoMassesWithRandomUnitsBenchmarks.cs
+++ b/UnitsNet.Benchmark/Operators/Additions/AddTwoMassesWithRandomUnitsBenchmarks.cs
@@ -26,8 +26,8 @@ public class AddTwoMassesWithRandomUnitsBenchmarks
[GlobalSetup]
public void PrepareQuantities()
{
- _operands = _random.GetRandomQuantities(LeftValue, Mass.Units, NbOperations)
- .Zip(_random.GetRandomQuantities(RightValue, Mass.Units, NbOperations),
+ _operands = _random.GetRandomQuantities(LeftValue, Mass.Units.ToArray(), NbOperations)
+ .Zip(_random.GetRandomQuantities(RightValue, Mass.Units.ToArray(), NbOperations),
(left, right) => (left, right))
.ToArray();
}
diff --git a/UnitsNet.Benchmark/Operators/Additions/AddTwoTemperatureDeltasWithRandomUnitsBenchmarks.cs b/UnitsNet.Benchmark/Operators/Additions/AddTwoTemperatureDeltasWithRandomUnitsBenchmarks.cs
index a3239d3010..3f61a4973d 100644
--- a/UnitsNet.Benchmark/Operators/Additions/AddTwoTemperatureDeltasWithRandomUnitsBenchmarks.cs
+++ b/UnitsNet.Benchmark/Operators/Additions/AddTwoTemperatureDeltasWithRandomUnitsBenchmarks.cs
@@ -26,8 +26,8 @@ public class AddTwoTemperatureDeltasWithRandomUnitsBenchmarks
[GlobalSetup]
public void PrepareQuantities()
{
- _operands = _random.GetRandomQuantities(LeftValue, TemperatureDelta.Units, NbOperations)
- .Zip(_random.GetRandomQuantities(RightValue, TemperatureDelta.Units, NbOperations),
+ _operands = _random.GetRandomQuantities(LeftValue, TemperatureDelta.Units.ToArray(), NbOperations)
+ .Zip(_random.GetRandomQuantities(RightValue, TemperatureDelta.Units.ToArray(), NbOperations),
(left, right) => (left, right))
.ToArray();
}
diff --git a/UnitsNet.Benchmark/Operators/Additions/AddTwoTemperatureDeltasWithSameUnitsBenchmarks.cs b/UnitsNet.Benchmark/Operators/Additions/AddTwoTemperatureDeltasWithSameUnitsBenchmarks.cs
index 03c93cfee9..963bc588dd 100644
--- a/UnitsNet.Benchmark/Operators/Additions/AddTwoTemperatureDeltasWithSameUnitsBenchmarks.cs
+++ b/UnitsNet.Benchmark/Operators/Additions/AddTwoTemperatureDeltasWithSameUnitsBenchmarks.cs
@@ -29,8 +29,8 @@ public class AddTwoTemperatureDeltasWithSameUnitsBenchmarks
[GlobalSetup]
public void PrepareQuantities()
{
- _operands = _random.GetRandomQuantities(LeftValue, TemperatureDelta.Units, NbOperations)
- .Zip(_random.GetRandomQuantities(RightValue, TemperatureDelta.Units, NbOperations),
+ _operands = _random.GetRandomQuantities(LeftValue, TemperatureDelta.Units.ToArray(), NbOperations)
+ .Zip(_random.GetRandomQuantities(RightValue, TemperatureDelta.Units.ToArray(), NbOperations),
(left, right) => (left, right))
.ToArray();
}
diff --git a/UnitsNet.Benchmark/Operators/Additions/AddTwoVolumesWithRandomUnitsBenchmarks.cs b/UnitsNet.Benchmark/Operators/Additions/AddTwoVolumesWithRandomUnitsBenchmarks.cs
index dcf3224e0b..b0cde2daa1 100644
--- a/UnitsNet.Benchmark/Operators/Additions/AddTwoVolumesWithRandomUnitsBenchmarks.cs
+++ b/UnitsNet.Benchmark/Operators/Additions/AddTwoVolumesWithRandomUnitsBenchmarks.cs
@@ -26,8 +26,8 @@ public class AddTwoVolumesWithRandomUnitsBenchmarks
[GlobalSetup]
public void PrepareQuantities()
{
- _operands = _random.GetRandomQuantities(LeftValue, Volume.Units, NbOperations)
- .Zip(_random.GetRandomQuantities(RightValue, Volume.Units, NbOperations),
+ _operands = _random.GetRandomQuantities(LeftValue, Volume.Units.ToArray(), NbOperations)
+ .Zip(_random.GetRandomQuantities(RightValue, Volume.Units.ToArray(), NbOperations),
(left, right) => (left, right))
.ToArray();
}
diff --git a/UnitsNet.Benchmark/Operators/Additions/SumOfMassesWithRandomUnitsBenchmarks.cs b/UnitsNet.Benchmark/Operators/Additions/SumOfMassesWithRandomUnitsBenchmarks.cs
index 696242b9b7..3a59f6b6ca 100644
--- a/UnitsNet.Benchmark/Operators/Additions/SumOfMassesWithRandomUnitsBenchmarks.cs
+++ b/UnitsNet.Benchmark/Operators/Additions/SumOfMassesWithRandomUnitsBenchmarks.cs
@@ -25,7 +25,7 @@ public class SumOfMassesWithRandomUnitsBenchmarks
[GlobalSetup]
public void PrepareQuantities()
{
- _quantities = _random.GetRandomQuantities(Value, Mass.Units, NbOperations).ToArray();
+ _quantities = _random.GetRandomQuantities(Value, Mass.Units.ToArray(), NbOperations).ToArray();
}
[Benchmark(Baseline = true)]
diff --git a/UnitsNet.Benchmark/Operators/Additions/SumOfTemperatureDeltasWithRandomUnitsBenchmarks.cs b/UnitsNet.Benchmark/Operators/Additions/SumOfTemperatureDeltasWithRandomUnitsBenchmarks.cs
index 65e135e3ae..cd9877e6bc 100644
--- a/UnitsNet.Benchmark/Operators/Additions/SumOfTemperatureDeltasWithRandomUnitsBenchmarks.cs
+++ b/UnitsNet.Benchmark/Operators/Additions/SumOfTemperatureDeltasWithRandomUnitsBenchmarks.cs
@@ -25,7 +25,7 @@ public class SumOfTemperatureDeltasWithRandomUnitsBenchmarks
[GlobalSetup]
public void PrepareQuantities()
{
- _quantities = _random.GetRandomQuantities(Value, TemperatureDelta.Units, NbOperations).ToArray();
+ _quantities = _random.GetRandomQuantities(Value, TemperatureDelta.Units.ToArray(), NbOperations).ToArray();
}
[Benchmark(Baseline = true)]
diff --git a/UnitsNet.Benchmark/Operators/Additions/SumOfVolumesWithRandomUnitsBenchmarks.cs b/UnitsNet.Benchmark/Operators/Additions/SumOfVolumesWithRandomUnitsBenchmarks.cs
index 76beab1238..c7bf590527 100644
--- a/UnitsNet.Benchmark/Operators/Additions/SumOfVolumesWithRandomUnitsBenchmarks.cs
+++ b/UnitsNet.Benchmark/Operators/Additions/SumOfVolumesWithRandomUnitsBenchmarks.cs
@@ -25,7 +25,7 @@ public class SumOfVolumesWithRandomUnitsBenchmarks
[GlobalSetup]
public void PrepareQuantities()
{
- _quantities = _random.GetRandomQuantities(Value, Volume.Units, NbOperations).ToArray();
+ _quantities = _random.GetRandomQuantities(Value, Volume.Units.ToArray(), NbOperations).ToArray();
Quantity.From(Value, Volume.BaseUnit); // TODO we need a better way to "disable" the lazy loading of the _quantitiesByUnitType (QuantityInfoLookup)
Console.Out.WriteLine("Quantities prepared: starting unit = {0}", _quantities[0].Unit);
}
diff --git a/UnitsNet.Benchmark/Operators/Additions/SumOfVolumesWithRandomUnitsWithIteratorBenchmarks.cs b/UnitsNet.Benchmark/Operators/Additions/SumOfVolumesWithRandomUnitsWithIteratorBenchmarks.cs
index 624a0ee775..2cf21ae684 100644
--- a/UnitsNet.Benchmark/Operators/Additions/SumOfVolumesWithRandomUnitsWithIteratorBenchmarks.cs
+++ b/UnitsNet.Benchmark/Operators/Additions/SumOfVolumesWithRandomUnitsWithIteratorBenchmarks.cs
@@ -24,7 +24,7 @@ public class SumOfVolumesWithRandomUnitsWithIteratorBenchmarks
[GlobalSetup]
public void PrepareQuantities()
{
- _quantities = _random.GetRandomQuantities(Value, Volume.Units, NbOperations).ToArray();
+ _quantities = _random.GetRandomQuantities(Value, Volume.Units.ToArray(), NbOperations).ToArray();
Quantity.From(Value, Volume.BaseUnit); // TODO we need a better way to "disable" the lazy loading of the _quantitiesByUnitType (QuantityInfoLookup)
Console.Out.WriteLine("Quantities prepared: starting unit = {0}", _quantities[0].Unit);
}
diff --git a/UnitsNet.Benchmark/Operators/Divisions/MassDividedByVolumeWithRandomUnitsBenchmarks.cs b/UnitsNet.Benchmark/Operators/Divisions/MassDividedByVolumeWithRandomUnitsBenchmarks.cs
index e880d6185d..581a282700 100644
--- a/UnitsNet.Benchmark/Operators/Divisions/MassDividedByVolumeWithRandomUnitsBenchmarks.cs
+++ b/UnitsNet.Benchmark/Operators/Divisions/MassDividedByVolumeWithRandomUnitsBenchmarks.cs
@@ -26,8 +26,8 @@ public class MassDividedByVolumeWithRandomUnitsBenchmarks
[GlobalSetup]
public void PrepareQuantities()
{
- _operands = _random.GetRandomQuantities(MassValue, Mass.Units, NbOperations)
- .Zip(_random.GetRandomQuantities(VolumeValue, Volume.Units, NbOperations), (mass, volume) => (volume: mass, density: volume))
+ _operands = _random.GetRandomQuantities(MassValue, Mass.Units.ToArray(), NbOperations)
+ .Zip(_random.GetRandomQuantities(VolumeValue, Volume.Units.ToArray(), NbOperations), (mass, volume) => (volume: mass, density: volume))
.ToArray();
}
diff --git a/UnitsNet.Benchmark/Operators/Multiplications/VolumeTimesDensityWithRandomUnitsBenchmarks.cs b/UnitsNet.Benchmark/Operators/Multiplications/VolumeTimesDensityWithRandomUnitsBenchmarks.cs
index db2a40c94b..b9e4c2f56b 100644
--- a/UnitsNet.Benchmark/Operators/Multiplications/VolumeTimesDensityWithRandomUnitsBenchmarks.cs
+++ b/UnitsNet.Benchmark/Operators/Multiplications/VolumeTimesDensityWithRandomUnitsBenchmarks.cs
@@ -26,8 +26,8 @@ public class VolumeTimesDensityWithRandomUnitsBenchmarks
[GlobalSetup]
public void PrepareQuantities()
{
- _operands = _random.GetRandomQuantities(VolumeValue, Volume.Units, NbOperations)
- .Zip(_random.GetRandomQuantities(DensityValue, Density.Units, NbOperations),
+ _operands = _random.GetRandomQuantities(VolumeValue, Volume.Units.ToArray(), NbOperations)
+ .Zip(_random.GetRandomQuantities(DensityValue, Density.Units.ToArray(), NbOperations),
(volume, density) => (volume, density))
.ToArray();
}
diff --git a/UnitsNet.Serialization.JsonNet/AbbreviatedUnitsConverter.cs b/UnitsNet.Serialization.JsonNet/AbbreviatedUnitsConverter.cs
index 27eb4149fe..10fc5b9b19 100644
--- a/UnitsNet.Serialization.JsonNet/AbbreviatedUnitsConverter.cs
+++ b/UnitsNet.Serialization.JsonNet/AbbreviatedUnitsConverter.cs
@@ -29,7 +29,7 @@ public class AbbreviatedUnitsConverter : NullableQuantityConverter
private readonly UnitAbbreviationsCache _abbreviations;
private readonly IEqualityComparer _propertyComparer;
- private readonly IDictionary _quantities;
+ private readonly IReadOnlyDictionary _quantities;
private readonly UnitParser _unitParser;
///
@@ -45,7 +45,7 @@ public AbbreviatedUnitsConverter()
///
/// The comparer used to compare the property/quantity names (e.g. StringComparer.OrdinalIgnoreCase)
public AbbreviatedUnitsConverter(IEqualityComparer comparer)
- : this(new Dictionary(Quantity.ByName, comparer), UnitsNetSetup.Default.UnitAbbreviations, comparer)
+ : this(Quantity.ByName, UnitsNetSetup.Default.UnitAbbreviations, comparer)
{
}
@@ -55,7 +55,7 @@ public AbbreviatedUnitsConverter(IEqualityComparer comparer)
/// The dictionary of quantity names
/// The unit abbreviations used for the serialization
/// The comparer used to compare the property names (e.g. StringComparer.OrdinalIgnoreCase)
- public AbbreviatedUnitsConverter(IDictionary quantities, UnitAbbreviationsCache abbreviations, IEqualityComparer propertyComparer)
+ public AbbreviatedUnitsConverter(IReadOnlyDictionary quantities, UnitAbbreviationsCache abbreviations, IEqualityComparer propertyComparer)
{
_quantities = quantities;
_abbreviations = abbreviations;
diff --git a/UnitsNet.Serialization.JsonNet/UnitsNetBaseJsonConverter.cs b/UnitsNet.Serialization.JsonNet/UnitsNetBaseJsonConverter.cs
index 87b5309c6d..2ba1d5aead 100644
--- a/UnitsNet.Serialization.JsonNet/UnitsNetBaseJsonConverter.cs
+++ b/UnitsNet.Serialization.JsonNet/UnitsNetBaseJsonConverter.cs
@@ -21,7 +21,7 @@ public abstract class UnitsNetBaseJsonConverter : NullableQuantityConverter
/// Register custom types so that the converter can instantiate these quantities.
- /// Instead of calling , the will be used to instantiate the object.
+ /// Instead of calling , the will be used to instantiate the object.
/// It is therefore assumed that the constructor of is specified with new T(double value, typeof() unit).
/// Registering the same multiple times, it will overwrite the one registered.
///
diff --git a/UnitsNet.Tests/CustomQuantities/HowMuch.cs b/UnitsNet.Tests/CustomQuantities/HowMuch.cs
index 40ed9752e6..6703471241 100644
--- a/UnitsNet.Tests/CustomQuantities/HowMuch.cs
+++ b/UnitsNet.Tests/CustomQuantities/HowMuch.cs
@@ -1,4 +1,5 @@
using System;
+using UnitsNet.Units;
namespace UnitsNet.Tests.CustomQuantities
{
@@ -6,51 +7,62 @@ namespace UnitsNet.Tests.CustomQuantities
///
/// Example of a custom/third-party quantity implementation, for plugging in quantities and units at runtime.
///
- public readonly struct HowMuch : IQuantity
+ public readonly struct HowMuch : IQuantity
{
public HowMuch(double value, HowMuchUnit unit)
{
Unit = unit;
Value = value;
}
-
+
public static HowMuch From(double value, HowMuchUnit unit)
{
return new HowMuch(value, unit);
}
- public bool Equals(IQuantity? other, IQuantity tolerance) => throw new NotImplementedException();
+ public double As(HowMuchUnit unit)
+ {
+ throw new NotImplementedException();
+ }
- Enum IQuantity.Unit => Unit;
public HowMuchUnit Unit { get; }
public double Value { get; }
#region IQuantity
-
- private static readonly HowMuch Zero = new HowMuch(0, HowMuchUnit.Some);
-
- public BaseDimensions Dimensions => BaseDimensions.Dimensionless;
-
- public static QuantityInfo Info = new(
+
+ public static readonly QuantityInfo Info = new(
nameof(HowMuch),
- typeof(HowMuchUnit),
- new UnitInfo[]
+ HowMuchUnit.Some,
+ new UnitDefinition[]
{
- new UnitInfo(HowMuchUnit.Some, "Some", BaseUnits.Undefined, nameof(HowMuch)),
- new UnitInfo(HowMuchUnit.ATon, "Tons", BaseUnits.Undefined, nameof(HowMuch)),
- new UnitInfo(HowMuchUnit.AShitTon, "ShitTons", BaseUnits.Undefined, nameof(HowMuch)),
+ new(HowMuchUnit.Some, "Some", BaseUnits.Undefined),
+ new(HowMuchUnit.ATon, "Tons", new BaseUnits(mass: MassUnit.Tonne)),
+ new(HowMuchUnit.AShitTon, "ShitTons", BaseUnits.Undefined)
},
- HowMuchUnit.Some,
- Zero,
- BaseDimensions.Dimensionless);
+ new HowMuch(0, HowMuchUnit.Some),
+ new BaseDimensions(0, 1, 0, 0, 0, 0, 0),
+ From);
+
+ QuantityInfo IQuantity.QuantityInfo
+ {
+ get => Info;
+ }
+
+ QuantityInfo IQuantity.QuantityInfo
+ {
+ get => Info;
+ }
QuantityInfo IQuantity.QuantityInfo
{
- get { return Info; }
+ get => Info;
}
-
- public UnitKey UnitKey
+
+ public BaseDimensions Dimensions => Info.BaseDimensions;
+
+
+ UnitKey IQuantity.UnitKey
{
get => UnitKey.ForUnit(Unit);
}
@@ -65,12 +77,38 @@ public IQuantity ToUnit(Enum unit)
throw new ArgumentException("Must be of type HowMuchUnit.", nameof(unit));
}
+ public IQuantity ToUnit(HowMuchUnit unit)
+ {
+ throw new NotImplementedException();
+ }
+
+ IQuantity IQuantity.ToUnit(UnitSystem unitSystem)
+ {
+ throw new NotImplementedException();
+ }
+
public IQuantity ToUnit(UnitSystem unitSystem) => throw new NotImplementedException();
public override string ToString() => $"{Value} {Unit}";
public string ToString(string? format, IFormatProvider? formatProvider) => $"HowMuch ({format}, {formatProvider})";
public string ToString(IFormatProvider? provider) => $"HowMuch ({provider})";
+ public bool Equals(IQuantity? other, IQuantity tolerance) => throw new NotImplementedException();
+
+ public bool Equals(HowMuch other, HowMuch tolerance)
+ {
+ throw new NotImplementedException();
+ }
+
+#if !NET
+
+ QuantityInfo IQuantity.QuantityInfo
+ {
+ get { return Info; }
+ }
+
+ Enum IQuantity.Unit => Unit;
+#endif
#endregion
}
}
diff --git a/UnitsNet.Tests/QuantityInfoTest.cs b/UnitsNet.Tests/QuantityInfoTest.cs
index 420f726fcf..623bea64c2 100644
--- a/UnitsNet.Tests/QuantityInfoTest.cs
+++ b/UnitsNet.Tests/QuantityInfoTest.cs
@@ -1,264 +1,671 @@
// 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;
using System.Diagnostics.CodeAnalysis;
-using System.Linq;
+using System.Resources;
using UnitsNet.Tests.CustomQuantities;
-using UnitsNet.Units;
-using Xunit;
-namespace UnitsNet.Tests
+namespace UnitsNet.Tests;
+
+public class QuantityInfoTest
{
- public class QuantityInfoTest
- {
- private UnitInfo[] _lengthUnitInfos = Length.Info.UnitInfos.Cast().ToArray();
-
- [Fact]
- public void Constructor_AssignsProperties()
- {
- var expectedZero = Length.FromCentimeters(10);
- UnitInfo[] expectedUnitInfos = {
- new(LengthUnit.Centimeter, "Centimeters", new BaseUnits(LengthUnit.Centimeter), nameof(Length)),
- new(LengthUnit.Kilometer, "Kilometers", new BaseUnits(LengthUnit.Kilometer), nameof(Length))
- };
- var expectedBaseUnit = LengthUnit.Centimeter;
- var expectedBaseDimensions = Length.BaseDimensions;
-
- var info = new QuantityInfo(nameof(Length), typeof(LengthUnit), expectedUnitInfos,
- expectedBaseUnit, expectedZero, expectedBaseDimensions);
-
- Assert.Equal(expectedZero, info.Zero);
- Assert.Equal("Length", info.Name);
- Assert.Equal(expectedUnitInfos, info.UnitInfos);
- Assert.Equal(expectedBaseDimensions, info.BaseDimensions);
- }
-
- [Fact]
- public void Constructor_AssignsPropertiesForCustomQuantity()
- {
- var expectedZero = new HowMuch(10, HowMuchUnit.Some);
- UnitInfo[] expectedUnitInfos = {
- new(HowMuchUnit.Some, "Some", BaseUnits.Undefined, nameof(HowMuch)),
- new(HowMuchUnit.ATon, "Tons", BaseUnits.Undefined, nameof(HowMuch)),
- new(HowMuchUnit.AShitTon, "ShitTons", BaseUnits.Undefined, nameof(HowMuch))
- };
- var expectedBaseUnit = HowMuchUnit.Some;
- var expectedBaseDimensions = BaseDimensions.Dimensionless;
-
- var info = new QuantityInfo(nameof(HowMuch), typeof(HowMuchUnit), expectedUnitInfos,
- expectedBaseUnit, expectedZero, expectedBaseDimensions);
-
- Assert.Equal(expectedZero, info.Zero);
- Assert.Equal(nameof(HowMuch), info.Name);
- Assert.Equal(expectedUnitInfos, info.UnitInfos);
- Assert.Equal(expectedBaseDimensions, info.BaseDimensions);
- }
-
- [Fact]
- public void GenericsConstructor_AssignsProperties()
- {
- var expectedZero = Length.FromCentimeters(10);
- UnitInfo[] expectedUnitInfos = {
- new(LengthUnit.Centimeter, "Centimeters", new BaseUnits(LengthUnit.Centimeter), nameof(Length)),
- new(LengthUnit.Kilometer,"Kilometers", new BaseUnits(LengthUnit.Kilometer), nameof(Length))
- };
- var expectedBaseUnit = LengthUnit.Centimeter;
- var expectedBaseDimensions = Length.BaseDimensions;
-
- var info = new QuantityInfo(nameof(Length), expectedUnitInfos, expectedBaseUnit, expectedZero, expectedBaseDimensions);
- Assert.Equal(expectedZero, info.Zero);
- Assert.Equal("Length", info.Name);
- Assert.Equal(expectedUnitInfos, info.UnitInfos);
- Assert.Equal(expectedBaseDimensions, info.BaseDimensions);
- }
-
- [Fact]
- [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
- public void Constructor_GivenNullAsUnitInfos_ThrowsArgumentNullException()
- {
- Assert.Throws(() => new QuantityInfo(nameof(Length), typeof(LengthUnit),
- null!, Length.BaseUnit, Length.Zero, Length.BaseDimensions));
- }
-
- [Fact]
- [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
- public void GenericsConstructor_GivenNullAsUnitInfos_ThrowsArgumentNullException()
- {
- Assert.Throws(() => new QuantityInfo(nameof(Length),
- null!, Length.BaseUnit, Length.Zero, Length.BaseDimensions));
- }
-
- [Fact]
- [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
- public void Constructor_GivenNullAsBaseUnit_ThrowsArgumentNullException()
- {
- Assert.Throws(() => new QuantityInfo(nameof(Length), typeof(LengthUnit),
- _lengthUnitInfos, null!, Length.Zero, Length.BaseDimensions));
- }
-
- [Fact]
- [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
- public void Constructor_GivenNullAsZero_ThrowsArgumentNullException()
- {
- Assert.Throws(() => new QuantityInfo(nameof(Length), typeof(LengthUnit),
- _lengthUnitInfos, Length.BaseUnit, null!, Length.BaseDimensions));
- }
-
- [Fact]
- [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
- public void GenericsConstructor_GivenNullAsZero_ThrowsArgumentNullException()
- {
- Assert.Throws(() => new QuantityInfo(nameof(Length),
- Length.Info.UnitInfos, Length.BaseUnit, null!, Length.BaseDimensions));
- }
-
- [Fact]
- [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
- public void Constructor_GivenNullAsBaseDimensions_ThrowsArgumentNullException()
- {
- Assert.Throws(() => new QuantityInfo(nameof(Length), typeof(LengthUnit),
- _lengthUnitInfos, Length.BaseUnit, Length.Zero, null!));
- }
-
- [Fact]
- [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
- public void GenericsConstructor_GivenNullAsBaseDimensions_ThrowsArgumentNullException()
- {
- Assert.Throws(() => new QuantityInfo(nameof(Length),
- Length.Info.UnitInfos, Length.BaseUnit, Length.Zero, null!));
- }
- [Fact]
- [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
- public void Constructor2_GivenNullAsUnitInfos_ThrowsArgumentNullException()
- {
- Assert.Throws(() => new QuantityInfo(Length.Info.Name, typeof(LengthUnit),
- null!, Length.BaseUnit, Length.Zero, Length.BaseDimensions));
- }
-
- [Fact]
- [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
- public void GenericsConstructor2_GivenNullAsUnitInfos_ThrowsArgumentNullException()
- {
- Assert.Throws(() => new QuantityInfo(Length.Info.Name,
- null!, Length.BaseUnit, Length.Zero, Length.BaseDimensions));
- }
-
- [Fact]
- [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
- public void Constructor2_GivenNullAsBaseUnit_ThrowsArgumentNullException()
- {
- Assert.Throws(() => new QuantityInfo(Length.Info.Name, typeof(LengthUnit),
- _lengthUnitInfos, null!, Length.Zero, Length.BaseDimensions));
- }
-
- [Fact]
- [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
- public void Constructor2_GivenNullAsZero_ThrowsArgumentNullException()
- {
- Assert.Throws(() => new QuantityInfo(Length.Info.Name, typeof(LengthUnit),
- _lengthUnitInfos, Length.BaseUnit, null!, Length.BaseDimensions));
- }
-
- [Fact]
- [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
- public void GenericsConstructor2_GivenNullAsZero_ThrowsArgumentNullException()
+ [Fact]
+ [SuppressMessage("ReSharper", "ParameterOnlyUsedForPreconditionCheck.Local")]
+ public void Constructor_AssignsProperties()
+ {
+ UnitDefinition[] expectedUnitInfos =
+ [
+ new(LengthUnit.Centimeter, "Centimeters", new BaseUnits(LengthUnit.Centimeter)),
+ new(LengthUnit.Kilometer, "Kilometers", new BaseUnits(LengthUnit.Kilometer))
+ ];
+ const LengthUnit expectedBaseUnit = LengthUnit.Centimeter;
+ var expectedZero = Length.FromCentimeters(10);
+ BaseDimensions expectedBaseDimensions = Length.BaseDimensions;
+ var abbreviations = new ResourceManager("UnitsNet.GeneratedCode.Resources.Length", typeof(Length).Assembly);
+
+ var quantityInfo = new QuantityInfo(nameof(Length), expectedBaseUnit, expectedUnitInfos, expectedZero, expectedBaseDimensions,
+ Length.From, abbreviations);
+
+ Assert.Equal(nameof(Length), quantityInfo.Name);
+ Assert.Equal(typeof(Length), quantityInfo.QuantityType);
+ Assert.Equal(typeof(LengthUnit), quantityInfo.UnitType);
+
+ // BaseUnitInfo
+ Assert.Multiple(() =>
+ {
+ UnitInfo baseUnitInfo = quantityInfo.BaseUnitInfo;
+ Assert.Equal(expectedBaseUnit, baseUnitInfo.Value);
+ }, () =>
+ {
+ QuantityInfo genericQuantityInfo = quantityInfo;
+ UnitInfo unitInfos = genericQuantityInfo.BaseUnitInfo;
+ Assert.Equal(quantityInfo.BaseUnitInfo, unitInfos);
+ }, () =>
+ {
+ QuantityInfo genericQuantityInfo = quantityInfo;
+ UnitInfo unitInfos = genericQuantityInfo.BaseUnitInfo;
+ Assert.Equal(quantityInfo.BaseUnitInfo, unitInfos);
+ });
+
+ // UnitInfos
+ Assert.Multiple(() =>
+ {
+ Assert.Collection(quantityInfo.UnitInfos, firstUnitInfo =>
+ {
+ Assert.Equal(LengthUnit.Centimeter, firstUnitInfo.Value);
+ Assert.Equal(expectedUnitInfos[0].Name, firstUnitInfo.Name);
+ Assert.Equal(expectedUnitInfos[0].PluralName, firstUnitInfo.PluralName);
+ Assert.Equal(expectedUnitInfos[0].BaseUnits, firstUnitInfo.BaseUnits);
+ Assert.Equal(quantityInfo, firstUnitInfo.QuantityInfo);
+ }, secondUnitInfo =>
+ {
+ Assert.Equal(LengthUnit.Kilometer, secondUnitInfo.Value);
+ Assert.Equal(expectedUnitInfos[1].Name, secondUnitInfo.Name);
+ Assert.Equal(expectedUnitInfos[1].PluralName, secondUnitInfo.PluralName);
+ Assert.Equal(expectedUnitInfos[1].BaseUnits, secondUnitInfo.BaseUnits);
+ Assert.Equal(quantityInfo, secondUnitInfo.QuantityInfo);
+ });
+ }, () =>
+ {
+ QuantityInfo genericQuantityInfo = quantityInfo;
+ IReadOnlyCollection> unitInfos = genericQuantityInfo.UnitInfos;
+ Assert.Equal(quantityInfo.UnitInfos, unitInfos);
+ }, () =>
+ {
+ QuantityInfo genericQuantityInfo = quantityInfo;
+ IReadOnlyCollection unitInfos = genericQuantityInfo.UnitInfos;
+ Assert.Equal(quantityInfo.UnitInfos, unitInfos);
+ });
+
+ // Zero
+ Assert.Multiple(() =>
+ {
+ Length zero = quantityInfo.Zero;
+ Assert.Equal(expectedZero, zero);
+ }, () =>
+ {
+ QuantityInfo genericQuantityInfo = quantityInfo;
+ IQuantity zero = genericQuantityInfo.Zero;
+ Assert.Equal(expectedZero, zero);
+ }, () =>
+ {
+ QuantityInfo genericQuantityInfo = quantityInfo;
+ IQuantity zero = genericQuantityInfo.Zero;
+ Assert.Equal(expectedZero, zero);
+ });
+
+ Assert.Equal(expectedBaseDimensions, quantityInfo.BaseDimensions);
+ Assert.Equal(abbreviations, quantityInfo.UnitAbbreviations);
+ }
+
+ [Fact]
+ [SuppressMessage("ReSharper", "ParameterOnlyUsedForPreconditionCheck.Local")]
+ public void Constructor_AssignsPropertiesForCustomQuantity()
+ {
+ UnitDefinition[] expectedUnitInfos =
+ [
+ new(HowMuchUnit.Some, "Some", BaseUnits.Undefined),
+ new(HowMuchUnit.ATon, "Tons", BaseUnits.Undefined),
+ new(HowMuchUnit.AShitTon, "ShitTons", BaseUnits.Undefined)
+ ];
+ const HowMuchUnit expectedBaseUnit = HowMuchUnit.Some;
+ var expectedZero = new HowMuch(10, HowMuchUnit.Some);
+ BaseDimensions expectedBaseDimensions = BaseDimensions.Dimensionless;
+
+ var quantityInfo = new QuantityInfo(nameof(HowMuch), expectedBaseUnit,
+ expectedUnitInfos, expectedZero, expectedBaseDimensions, HowMuch.From);
+
+ Assert.Equal(nameof(HowMuch), quantityInfo.Name);
+ Assert.Equal(typeof(HowMuch), quantityInfo.QuantityType);
+ Assert.Equal(typeof(HowMuchUnit), quantityInfo.UnitType);
+ Assert.Equal(expectedBaseUnit, quantityInfo.BaseUnitInfo.Value);
+ Assert.Collection(quantityInfo.UnitInfos, firstUnitInfo =>
+ {
+ Assert.Equal(HowMuchUnit.Some, firstUnitInfo.Value);
+ Assert.Equal(expectedUnitInfos[0].Name, firstUnitInfo.Name);
+ Assert.Equal(expectedUnitInfos[0].PluralName, firstUnitInfo.PluralName);
+ Assert.Equal(expectedUnitInfos[0].BaseUnits, firstUnitInfo.BaseUnits);
+ Assert.Equal(quantityInfo, firstUnitInfo.QuantityInfo);
+ }, secondUnitInfo =>
+ {
+ Assert.Equal(HowMuchUnit.ATon, secondUnitInfo.Value);
+ Assert.Equal(expectedUnitInfos[1].Name, secondUnitInfo.Name);
+ Assert.Equal(expectedUnitInfos[1].PluralName, secondUnitInfo.PluralName);
+ Assert.Equal(expectedUnitInfos[1].BaseUnits, secondUnitInfo.BaseUnits);
+ Assert.Equal(quantityInfo, secondUnitInfo.QuantityInfo);
+ }, thirdUnitInfo =>
+ {
+ Assert.Equal(HowMuchUnit.AShitTon, thirdUnitInfo.Value);
+ Assert.Equal(expectedUnitInfos[2].Name, thirdUnitInfo.Name);
+ Assert.Equal(expectedUnitInfos[2].PluralName, thirdUnitInfo.PluralName);
+ Assert.Equal(expectedUnitInfos[2].BaseUnits, thirdUnitInfo.BaseUnits);
+ Assert.Equal(quantityInfo, thirdUnitInfo.QuantityInfo);
+ });
+ Assert.Equal(expectedZero, quantityInfo.Zero);
+ Assert.Equal(expectedBaseDimensions, quantityInfo.BaseDimensions);
+ Assert.Null(quantityInfo.UnitAbbreviations);
+ }
+
+ [Fact]
+ public void Constructor_WithoutZero_UsesZeroBaseUnit()
+ {
+ UnitDefinition[] expectedUnitInfos =
+ [
+ new(HowMuchUnit.Some, "Some", BaseUnits.Undefined)
+ ];
+ const HowMuchUnit expectedBaseUnit = HowMuchUnit.Some;
+ BaseDimensions expectedBaseDimensions = BaseDimensions.Dimensionless;
+ var expectedZero = new HowMuch(0, HowMuchUnit.Some);
+
+ var quantityInfo = new QuantityInfo(nameof(HowMuch), expectedBaseUnit,
+ expectedUnitInfos, expectedBaseDimensions, HowMuch.From);
+
+ Assert.Equal(expectedZero, quantityInfo.Zero);
+ Assert.Equal(nameof(HowMuch), quantityInfo.Name);
+ Assert.Equal(expectedBaseUnit, quantityInfo.BaseUnitInfo.Value);
+ Assert.Single(quantityInfo.UnitInfos, unitInfo =>
+ expectedBaseUnit == unitInfo.Value &&
+ expectedUnitInfos[0].Name == unitInfo.Name &&
+ expectedUnitInfos[0].PluralName == unitInfo.PluralName &&
+ expectedUnitInfos[0].BaseUnits == unitInfo.BaseUnits
+ );
+ Assert.Equal(expectedBaseDimensions, quantityInfo.BaseDimensions);
+ Assert.Null(quantityInfo.UnitAbbreviations);
+ }
+
+ [Fact]
+ public void Constructor_WithoutName_UsesDefaultQuantityTypeName()
+ {
+ UnitDefinition[] expectedUnitInfos =
+ [
+ new(HowMuchUnit.Some, "Some", BaseUnits.Undefined)
+ ];
+ const HowMuchUnit expectedBaseUnit = HowMuchUnit.Some;
+ var expectedZero = new HowMuch(0, HowMuchUnit.Some);
+ BaseDimensions expectedBaseDimensions = BaseDimensions.Dimensionless;
+ var abbreviations = new ResourceManager("UnitsNet.GeneratedCode.Resources.Length", typeof(Length).Assembly);
+
+ var quantityInfo =
+ new QuantityInfo(expectedBaseUnit, expectedUnitInfos, expectedBaseDimensions, HowMuch.From, abbreviations);
+
+ Assert.Equal(expectedZero, quantityInfo.Zero);
+ Assert.Equal(nameof(HowMuch), quantityInfo.Name);
+ Assert.Equal(expectedBaseUnit, quantityInfo.BaseUnitInfo.Value);
+ Assert.Single(quantityInfo.UnitInfos, firstUnitInfo =>
+ expectedBaseUnit == firstUnitInfo.Value &&
+ expectedUnitInfos[0].Name == firstUnitInfo.Name &&
+ expectedUnitInfos[0].PluralName == firstUnitInfo.PluralName &&
+ expectedUnitInfos[0].BaseUnits == firstUnitInfo.BaseUnits
+ );
+ Assert.Equal(expectedBaseDimensions, quantityInfo.BaseDimensions);
+ Assert.Equal(abbreviations, quantityInfo.UnitAbbreviations);
+ }
+
+ [Fact]
+ [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
+ public void Constructor_GivenNullAsQuantityName_ThrowsArgumentNullException()
+ {
+ Assert.Throws(() => new QuantityInfo(null!,
+ LengthUnit.Meter, Length.Info.UnitInfos, Length.BaseDimensions, Length.From));
+ }
+
+ [Fact]
+ [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
+ public void Constructor_GivenNullAsUnitInfos_ThrowsArgumentNullException()
+ {
+ IEnumerable> nullCollection = null!;
+ Assert.Throws(() => new QuantityInfo(nameof(Length),
+ LengthUnit.Meter, nullCollection, Length.BaseDimensions, Length.From));
+ }
+
+ [Fact]
+ [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
+ public void Constructor_GivenANullUnitInfo_ThrowsArgumentNullException()
+ {
+ IEnumerable> collectionContainingANull = [null!];
+#if NET
+ Assert.Throws(() => new QuantityInfo(nameof(Length),
+ LengthUnit.Meter, collectionContainingANull, Length.BaseDimensions, Length.From));
+#else
+ Assert.Throws(() => new QuantityInfo(nameof(Length),
+ LengthUnit.Meter, collectionContainingANull, Length.BaseDimensions, Length.From));
+#endif
+ }
+
+ [Fact]
+ [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
+ public void Constructor_GivenNullAsBaseDimensions_ThrowsArgumentNullException()
+ {
+ Assert.Throws(() => new QuantityInfo(nameof(Length),
+ LengthUnit.Meter, Length.Info.UnitInfos, null!, Length.From));
+ }
+
+ [Fact]
+ public void Constructor_GivenAMissingBaseUnitDefinition_ThrowsUnitNotFoundException()
+ {
+ Assert.Throws(() =>
+ new QuantityInfo(Length.BaseUnit, [], Length.BaseDimensions, Length.From));
+ }
+
+ [Fact]
+ public void GetUnitInfoFor_GivenNullAsBaseUnits_ThrowsArgumentNullException()
+ {
+ Assert.Multiple(() =>
{
- Assert.Throws(() => new QuantityInfo(Length.Info.Name,
- Length.Info.UnitInfos, Length.BaseUnit, null!, Length.BaseDimensions));
- }
+ QuantityInfo quantityInfo = Length.Info;
+ Assert.Throws(() => quantityInfo.GetUnitInfoFor(null!));
+ }, () =>
+ {
+ QuantityInfo quantityInfo = Length.Info;
+ Assert.Throws(() => quantityInfo.GetUnitInfoFor(null!));
+ }, () =>
+ {
+ QuantityInfo quantityInfo = Length.Info;
+ Assert.Throws(() => quantityInfo.GetUnitInfoFor(null!));
+ });
+ }
- [Fact]
- [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
- public void Constructor2_GivenNullAsBaseDimensions_ThrowsArgumentNullException()
+ [Fact]
+ public void GetUnitInfoFor_GivenBaseUnitsWithNoMatch_ThrowsInvalidOperationException()
+ {
+ var baseUnitsWithNoMatch = new BaseUnits(mass: MassUnit.Kilogram);
+ Assert.Multiple(() =>
+ {
+ QuantityInfo quantityInfo = Length.Info;
+ Assert.Throws(() => quantityInfo.GetUnitInfoFor(baseUnitsWithNoMatch));
+ }, () =>
+ {
+ QuantityInfo quantityInfo = Length.Info;
+ Assert.Throws(() => quantityInfo.GetUnitInfoFor(baseUnitsWithNoMatch));
+ }, () =>
{
- Assert.Throws(() => new QuantityInfo(Length.Info.Name, typeof(LengthUnit),
- _lengthUnitInfos, Length.BaseUnit, Length.Zero, null!));
- }
+ QuantityInfo quantityInfo = Length.Info;
+ Assert.Throws(() => quantityInfo.GetUnitInfoFor(baseUnitsWithNoMatch));
+ });
+ }
- [Fact]
- [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
- public void GenericsConstructor2_GivenNullAsBaseDimensions_ThrowsArgumentNullException()
+ [Fact]
+ public void GetUnitInfoFor_GivenBaseUnitsWithMultipleMatches_ThrowsInvalidOperationException()
+ {
+ var baseUnits = new BaseUnits(LengthUnit.Meter);
+ UnitDefinition[] duplicateBaseUnits =
+ [
+ new(LengthUnit.Meter, "Meters", baseUnits),
+ new(LengthUnit.Foot, "Feet", baseUnits)
+ ];
+ BaseDimensions dimensions = Length.BaseDimensions;
+ Assert.Multiple(() =>
+ {
+ var quantityInfo = new QuantityInfo(LengthUnit.Meter, duplicateBaseUnits, dimensions, Length.From);
+ Assert.Throws(() => quantityInfo.GetUnitInfoFor(baseUnits));
+ }, () =>
+ {
+ QuantityInfo genericQuantityInfo = new QuantityInfo(LengthUnit.Meter, duplicateBaseUnits, dimensions, Length.From);
+ Assert.Throws(() => genericQuantityInfo.GetUnitInfoFor(baseUnits));
+ }, () =>
{
- Assert.Throws(() => new QuantityInfo(Length.Info.Name,
- Length.Info.UnitInfos, Length.BaseUnit, Length.Zero, null!));
- }
+ QuantityInfo genericQuantityInfo = new QuantityInfo(LengthUnit.Meter, duplicateBaseUnits, dimensions, Length.From);
+ Assert.Throws(() => genericQuantityInfo.GetUnitInfoFor(baseUnits));
+ });
+ }
+
+ [Fact]
+ public void GetUnitInfoFor_GivenBaseUnitsWithOneMatch_ReturnsTheMatch()
+ {
+ var baseUnitsWithOneMatch = new BaseUnits(LengthUnit.Foot);
+ UnitInfo expectedUnitInfo = Length.Info[LengthUnit.Foot];
- [Fact]
- public void GetUnitInfoFor_GivenNullAsBaseUnits_ThrowsArgumentNullException()
+ Assert.Multiple(() =>
{
- Assert.Throws(() => Length.Info.GetUnitInfoFor(null!));
- }
+ QuantityInfo quantityInfo = Length.Info;
- [Fact]
- public void GetUnitInfoFor_GivenBaseUnitsWithNoMatch_ThrowsInvalidOperationException()
+ UnitInfo result = quantityInfo.GetUnitInfoFor(baseUnitsWithOneMatch);
+
+ Assert.Equal(expectedUnitInfo, result);
+ }, () =>
{
- var baseUnitsWithNoMatch = new BaseUnits(mass: MassUnit.Kilogram);
- Assert.Throws(() => Length.Info.GetUnitInfoFor(baseUnitsWithNoMatch));
- }
+ QuantityInfo quantityInfo = Length.Info;
+
+ UnitInfo result = quantityInfo.GetUnitInfoFor(baseUnitsWithOneMatch);
- [Fact]
- public void GetUnitInfoFor_GivenBaseUnitsWithMultipleMatches_ThrowsInvalidOperationException()
+ Assert.Equal(expectedUnitInfo, result);
+ }, () =>
{
- var baseUnits = new BaseUnits(LengthUnit.Meter);
+ QuantityInfo quantityInfo = Length.Info;
- var quantityInfo = new QuantityInfo(Length.Info.Name,
- new UnitInfo[] {
- new(LengthUnit.Meter, "Meters", baseUnits, nameof(Length)),
- new(LengthUnit.Foot, "Feet", baseUnits, nameof(Length))
- },
- LengthUnit.Meter, Length.Zero, Length.BaseDimensions);
+ UnitInfo result = quantityInfo.GetUnitInfoFor(baseUnitsWithOneMatch);
- Assert.Throws(() => quantityInfo.GetUnitInfoFor(baseUnits));
- }
+ Assert.Equal(expectedUnitInfo, result);
+ });
+ }
- [Fact]
- public void GetUnitInfosFor_GivenNullAsBaseUnits_ThrowsArgumentNullException()
+ [Fact]
+ public void GetUnitInfosFor_GivenNullAsBaseUnits_ThrowsArgumentNullException()
+ {
+ Assert.Multiple(() =>
+ {
+ QuantityInfo quantityInfo = Length.Info;
+ Assert.Throws(() => quantityInfo.GetUnitInfosFor(null!));
+ }, () =>
{
- Assert.Throws(() => Length.Info.GetUnitInfosFor(null!));
- }
+ QuantityInfo quantityInfo = Length.Info;
+ Assert.Throws(() => quantityInfo.GetUnitInfosFor(null!));
+ }, () =>
+ {
+ QuantityInfo quantityInfo = Length.Info;
+ Assert.Throws(() => quantityInfo.GetUnitInfosFor(null!));
+ });
+ }
- [Fact]
- public void GetUnitInfosFor_GivenBaseUnitsWithNoMatch_ReturnsEmpty()
+ [Fact]
+ public void GetUnitInfosFor_GivenBaseUnitsWithNoMatch_ReturnsEmpty()
+ {
+ var baseUnitsWithNoMatch = new BaseUnits(mass: MassUnit.Kilogram);
+ Assert.Multiple(() =>
+ {
+ QuantityInfo quantityInfo = Length.Info;
+
+ IEnumerable> result = quantityInfo.GetUnitInfosFor(baseUnitsWithNoMatch);
+
+ Assert.Empty(result);
+ }, () =>
{
- var baseUnitsWithNoMatch = new BaseUnits(mass: MassUnit.Kilogram);
- var result = Length.Info.GetUnitInfosFor(baseUnitsWithNoMatch);
+ QuantityInfo quantityInfo = Length.Info;
+
+ IEnumerable> result = quantityInfo.GetUnitInfosFor(baseUnitsWithNoMatch);
+
+ Assert.Empty(result);
+ }, () =>
+ {
+ QuantityInfo quantityInfo = Length.Info;
+
+ IEnumerable result = quantityInfo.GetUnitInfosFor(baseUnitsWithNoMatch);
+
Assert.Empty(result);
- }
-
- [Fact]
- public void GetUnitInfosFor_GivenBaseUnitsWithOneMatch_ReturnsOneMatch()
- {
- var baseUnitsWithOneMatch = new BaseUnits(LengthUnit.Foot);
- var result = Length.Info.GetUnitInfosFor(baseUnitsWithOneMatch);
- Assert.Collection(result, element1 => Assert.Equal(LengthUnit.Foot, element1.Value));
- }
-
- [Fact]
- [SuppressMessage("ReSharper", "ParameterOnlyUsedForPreconditionCheck.Local")]
- public void GetUnitInfosFor_GivenBaseUnitsWithMultipleMatches_ReturnsMultipleMatches()
- {
- var baseUnits = new BaseUnits(LengthUnit.Meter);
-
- var quantityInfo = new QuantityInfo(Length.Info.Name,
- new UnitInfo[] {
- new(LengthUnit.Meter, "Meters", baseUnits, nameof(Length)),
- new(LengthUnit.Foot, "Feet", baseUnits, nameof(Length)) },
- LengthUnit.Meter, Length.Zero, Length.BaseDimensions);
-
- var result = quantityInfo.GetUnitInfosFor(baseUnits);
-
- Assert.Collection(result,
- element1 =>
- {
- Assert.Equal(LengthUnit.Meter, element1.Value);
- Assert.Equal(baseUnits, element1.BaseUnits);
- },
- element2 =>
- {
- Assert.Equal(LengthUnit.Foot, element2.Value);
- Assert.Equal(baseUnits, element2.BaseUnits);
- } );
- }
+ });
+ }
+
+ [Fact]
+ public void GetUnitInfosFor_GivenBaseUnitsWithOneMatch_ReturnsOneMatch()
+ {
+ var baseUnitsWithOneMatch = new BaseUnits(LengthUnit.Foot);
+ IEnumerable> result = Length.Info.GetUnitInfosFor(baseUnitsWithOneMatch);
+ Assert.Collection(result, element1 => Assert.Equal(LengthUnit.Foot, element1.Value));
+ }
+
+ [Fact]
+ public void GetUnitInfosFor_GivenBaseUnitsWithMultipleMatches_ReturnsMultipleMatches()
+ {
+ var baseUnits = new BaseUnits(LengthUnit.Meter);
+
+ var quantityInfo = new QuantityInfo(Length.Info.Name,
+ LengthUnit.Meter, new UnitDefinition[] { new(LengthUnit.Meter, "Meters", baseUnits), new(LengthUnit.Foot, "Feet", baseUnits) },
+ Length.BaseDimensions, Length.From);
+
+ var result = quantityInfo.GetUnitInfosFor(baseUnits).ToList();
+
+ Assert.Equal(2, result.Count);
+ Assert.Contains(result, info => info.Value == LengthUnit.Meter && info.BaseUnits == baseUnits);
+ Assert.Contains(result, info => info.Value == LengthUnit.Foot && info.BaseUnits == baseUnits);
+ }
+
+ // [Fact]
+ // public void TryGetUnitInfo_WithEnum_ReturnsTheExpectedResult()
+ // {
+ // QuantityInfo quantityInfo = HowMuch.Info;
+ //
+ // var success = quantityInfo.TryGetUnitInfo(HowMuchUnit.ATon, out UnitInfo? unitInfo);
+ //
+ // Assert.True(success);
+ // Assert.Equal(HowMuchUnit.ATon, unitInfo!.Value);
+ // }
+ //
+ // [Fact]
+ // public void TryGetUnitInfo_WithInvalidEnum_ReturnsTheExpectedResult()
+ // {
+ // QuantityInfo quantityInfo = HowMuch.Info;
+ //
+ // var success = quantityInfo.TryGetUnitInfo(LengthUnit.Meter, out UnitInfo? unitInfo);
+ //
+ // Assert.False(success);
+ // Assert.Null(unitInfo);
+ // }
+
+ [Fact]
+ public void TryGetUnitInfo_WithUnit_ReturnsTheExpectedResult()
+ {
+ QuantityInfo quantityInfo = Mass.Info;
+
+ var success = quantityInfo.TryGetUnitInfo(MassUnit.Milligram, out UnitInfo? unitInfo);
+
+ Assert.True(success);
+ Assert.Equal(MassUnit.Milligram, unitInfo!.Value);
+ }
+
+ [Fact]
+ public void TryGetUnitInfo_WithInvalidUnit_ReturnsTheExpectedResult()
+ {
+ QuantityInfo quantityInfo = Mass.Info;
+
+ var success = quantityInfo.TryGetUnitInfo((MassUnit)(-1), out UnitInfo? unitInfo);
+
+ Assert.False(success);
+ Assert.Null(unitInfo);
+ }
+
+ [Fact]
+ public void Indexer_WithValidEnum_ReturnsTheTargetUnitInfo()
+ {
+ QuantityInfo quantityInfo = HowMuch.Info;
+
+ UnitInfo unitInfo = quantityInfo[HowMuchUnit.ATon];
+
+ Assert.Equal(HowMuchUnit.ATon, unitInfo.Value);
+ }
+
+ [Fact]
+ public void Indexer_WithInvalidEnum_ThrowsKeyNotFoundException()
+ {
+ QuantityInfo quantityInfo = HowMuch.Info;
+
+ Assert.Throws(() => quantityInfo[(HowMuchUnit)(-1)]);
+ }
+
+ [Fact]
+ public void Indexer_WithValidUnit_ReturnsTheTargetUnitInfo()
+ {
+ QuantityInfo quantityInfo = Mass.Info;
+
+ UnitInfo unitInfo = quantityInfo[MassUnit.Milligram];
+
+ Assert.Equal(MassUnit.Milligram, unitInfo.Value);
+ }
+
+ [Fact]
+ public void Indexer_WithInvalidUnit_ThrowsKeyNotFoundException()
+ {
+ QuantityInfo quantityInfo = Mass.Info;
+
+ Assert.Throws(() => quantityInfo[(MassUnit)(-1)]);
+ }
+
+ [Fact]
+ public void Indexer_WithValidUnitKey_ReturnsTheTargetUnitInfo()
+ {
+ QuantityInfo quantityInfo = Mass.Info;
+ var unitKey = UnitKey.ForUnit(MassUnit.Milligram);
+
+ UnitInfo unitInfo = quantityInfo[unitKey];
+
+ Assert.Equal(MassUnit.Milligram, unitInfo.Value);
+ }
+
+ [Fact]
+ public void Indexer_WithInvalidUnitKeyType_ThrowsInvalidOperationException()
+ {
+ QuantityInfo quantityInfo = Mass.Info;
+ var unitKey = UnitKey.ForUnit(LengthUnit.Meter);
+
+ Assert.Throws(() => quantityInfo[unitKey]);
+ }
+
+ [Fact]
+ public void Indexer_WithUnknownUnitKeyValue_ThrowsInvalidOperationException()
+ {
+ QuantityInfo quantityInfo = Mass.Info;
+ var unitKey = new UnitKey(typeof(MassUnit), -1);
+
+ Assert.Throws(() => quantityInfo[unitKey]);
+ }
+
+ [Fact]
+ public void UntypedIndexer_WithUnknownUnitKeyValue_ThrowsInvalidOperationException()
+ {
+ QuantityInfo quantityInfo = Mass.Info;
+ var unitKey = new UnitKey(typeof(MassUnit), -1);
+
+ Assert.Throws(() => quantityInfo[unitKey]);
+ }
+
+ [Theory]
+ [InlineData(1, MassUnit.Kilogram)]
+ [InlineData(2, MassUnit.Milligram)]
+ public void From_ValueAndUnit_ReturnsTheExpectedQuantity(double value, MassUnit unit)
+ {
+ Assert.Multiple(() =>
+ {
+ QuantityInfo quantityInfo = Mass.Info;
+
+ Mass quantity = quantityInfo.From(value, unit);
+
+ Assert.Equal(value, quantity.Value);
+ Assert.Equal(unit, quantity.Unit);
+ }, () =>
+ {
+ QuantityInfo quantityInfo = Mass.Info;
+
+ IQuantity quantity = quantityInfo.From(value, unit);
+
+ Assert.Equal(value, quantity.Value);
+ Assert.Equal(unit, quantity.Unit);
+ }, () =>
+ {
+ QuantityInfo quantityInfo = Mass.Info;
+
+ IQuantity quantity = quantityInfo.From(value, unit);
+
+ Assert.Equal(value, quantity.Value);
+ Assert.Equal(unit, quantity.Unit);
+ });
}
+
+ [Theory]
+ [InlineData(1, MassUnit.Kilogram)]
+ [InlineData(2, MassUnit.Milligram)]
+ public void From_ValueAndUnitKey_WithSameUnitType_ReturnsTheExpectedQuantity(double value, MassUnit unit)
+ {
+ IQuantityInstanceInfo quantityInfo = Mass.Info;
+
+ Mass quantity = quantityInfo.Create(value, UnitKey.ForUnit(unit));
+
+ Assert.Equal(value, quantity.Value);
+ Assert.Equal(unit, quantity.Unit);
+ }
+
+ [Theory]
+ [InlineData(1, MassUnit.Kilogram)]
+ [InlineData(2, MassUnit.Milligram)]
+ public void From_ValueAnEnum_WithSameUnitType_ReturnsTheExpectedQuantity(double value, Enum unit)
+ {
+ QuantityInfo quantityInfo = Mass.Info;
+
+ IQuantity quantity = quantityInfo.From(value, unit);
+
+ Assert.Equal(value, quantity.Value);
+ Assert.Equal(unit, quantity.Unit);
+ }
+
+ [Fact]
+ public void From_ValueAndUnitKey_WIthDifferentUnitType_ThrowsArgumentException()
+ {
+ IQuantityInstanceInfo quantityInfo = Mass.Info;
+ var unitKey = UnitKey.ForUnit(LengthUnit.Meter);
+
+ Assert.Throws(() => quantityInfo.Create(1, unitKey));
+ }
+
+ [Fact]
+ public void From_ValueAndEnum_WIthDifferentUnitType_ThrowsInvalidOperationException()
+ {
+ QuantityInfo quantityInfo = Mass.Info;
+
+ Assert.Throws(() => quantityInfo.From(1, LengthUnit.Meter));
+ }
+
+ [Fact]
+ public void ToString_ReturnsTheQuantityName()
+ {
+ QuantityInfo quantityInfo = Mass.Info;
+
+ Assert.Equal(quantityInfo.Name, quantityInfo.ToString());
+ }
+
+#if NET
+
+ [Fact]
+ public void Constructor_WithoutDelegate_UsesTheDefaultQuantityFrom()
+ {
+ UnitDefinition[] expectedUnitInfos =
+ [
+ new(HowMuchUnit.Some, "Some", BaseUnits.Undefined)
+ ];
+ const string quantityName = "How Much?";
+ const HowMuchUnit expectedBaseUnit = HowMuchUnit.Some;
+ var expectedZero = new HowMuch(0, HowMuchUnit.Some);
+ BaseDimensions expectedBaseDimensions = BaseDimensions.Dimensionless;
+ var abbreviations = new ResourceManager("UnitsNet.GeneratedCode.Resources.Length", typeof(Length).Assembly);
+
+ var quantityInfo = new QuantityInfo(quantityName, expectedBaseUnit, expectedUnitInfos, expectedBaseDimensions, abbreviations);
+
+ Assert.Equal(quantityName, quantityInfo.Name);
+ Assert.Equal(expectedZero, quantityInfo.Zero);
+ Assert.Equal(expectedBaseUnit, quantityInfo.BaseUnitInfo.Value);
+ Assert.Single(quantityInfo.UnitInfos, firstUnitInfo =>
+ expectedBaseUnit == firstUnitInfo.Value &&
+ expectedUnitInfos[0].Name == firstUnitInfo.Name &&
+ expectedUnitInfos[0].PluralName == firstUnitInfo.PluralName &&
+ expectedUnitInfos[0].BaseUnits == firstUnitInfo.BaseUnits
+ );
+ Assert.Equal(expectedBaseDimensions, quantityInfo.BaseDimensions);
+ Assert.Equal(abbreviations, quantityInfo.UnitAbbreviations);
+ }
+
+ [Fact]
+ public void Constructor_WithoutNameOrDelegate_UsesTheDefaultQuantityNameAndFrom()
+ {
+ UnitDefinition[] expectedUnitInfos =
+ [
+ new(HowMuchUnit.Some, "Some", BaseUnits.Undefined)
+ ];
+ const HowMuchUnit expectedBaseUnit = HowMuchUnit.Some;
+ var expectedZero = new HowMuch(0, HowMuchUnit.Some);
+ BaseDimensions expectedBaseDimensions = BaseDimensions.Dimensionless;
+ var abbreviations = new ResourceManager("UnitsNet.GeneratedCode.Resources.Length", typeof(Length).Assembly);
+
+ var quantityInfo = new QuantityInfo(expectedBaseUnit, expectedUnitInfos, expectedBaseDimensions, abbreviations);
+
+ Assert.Equal(expectedZero, quantityInfo.Zero);
+ Assert.Equal(nameof(HowMuch), quantityInfo.Name);
+ Assert.Equal(expectedBaseUnit, quantityInfo.BaseUnitInfo.Value);
+ Assert.Single(quantityInfo.UnitInfos, firstUnitInfo =>
+ expectedBaseUnit == firstUnitInfo.Value &&
+ expectedUnitInfos[0].Name == firstUnitInfo.Name &&
+ expectedUnitInfos[0].PluralName == firstUnitInfo.PluralName &&
+ expectedUnitInfos[0].BaseUnits == firstUnitInfo.BaseUnits
+ );
+ Assert.Equal(expectedBaseDimensions, quantityInfo.BaseDimensions);
+ Assert.Equal(abbreviations, quantityInfo.UnitAbbreviations);
+ }
+
+#endif
}
diff --git a/UnitsNet.Tests/QuantityTest.cs b/UnitsNet.Tests/QuantityTest.cs
index d683968a39..94b3e49926 100644
--- a/UnitsNet.Tests/QuantityTest.cs
+++ b/UnitsNet.Tests/QuantityTest.cs
@@ -1,12 +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;
-using System.Collections.Generic;
using System.Globalization;
-using System.Linq;
-using UnitsNet.Units;
-using Xunit;
using static System.Globalization.CultureInfo;
namespace UnitsNet.Tests
@@ -20,7 +15,7 @@ public class QuantityTest
[InlineData(double.NaN)]
[InlineData(double.PositiveInfinity)]
[InlineData(double.NegativeInfinity)]
- public void From_GivenNaNOrInfinity_DoNotThrowsArgumentException(double value)
+ public void From_GivenNaNOrInfinity_DoesNotThrowArgumentException(double value)
{
var exception = Record.Exception(() => Quantity.From(value, LengthUnit.Centimeter));
@@ -43,6 +38,12 @@ public void TryFrom_GivenNullUnit_ReturnsFalse()
Enum? nullUnit = null;
Assert.False(Quantity.TryFrom(1, nullUnit, out IQuantity? _));
}
+
+ [Fact]
+ public void TryFrom_GivenUnknownUnitType_ReturnsFalse()
+ {
+ Assert.False(Quantity.TryFrom(1, ConsoleColor.Red, out IQuantity? _));
+ }
[Fact]
public void From_GivenValueAndUnit_ReturnsQuantity()
@@ -52,6 +53,14 @@ public void From_GivenValueAndUnit_ReturnsQuantity()
Assert.Equal(Pressure.FromMegabars(3), Quantity.From(3, PressureUnit.Megabar));
}
+ [Fact]
+ public void FromQuantityInfo_ReturnsQuantityWithBaseUnit()
+ {
+ IQuantity quantity = Quantity.FromQuantityInfo(Length.Info, 1);
+ Assert.Equal(1, quantity.Value);
+ Assert.Equal(Length.BaseUnit, quantity.Unit);
+ }
+
[Fact]
public void ByName_GivenLength_ReturnsQuantityInfoForLength()
{
@@ -215,7 +224,7 @@ public void Types_ReturnsKnownQuantityTypes()
{
var knownQuantities = new List { Length.Info, Force.Info, Mass.Info };
- ICollection types = Quantity.ByName.Values;
+ IEnumerable types = Quantity.ByName.Values;
Assert.Superset(knownQuantities.ToHashSet(), types.ToHashSet());
}
diff --git a/UnitsNet.Tests/QuantityTests.cs b/UnitsNet.Tests/QuantityTests.cs
index e50a25ba23..26e61b917c 100644
--- a/UnitsNet.Tests/QuantityTests.cs
+++ b/UnitsNet.Tests/QuantityTests.cs
@@ -1,10 +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;
using System.Globalization;
-using UnitsNet.Units;
-using Xunit;
namespace UnitsNet.Tests
{
@@ -153,7 +150,7 @@ public void From_InvalidUnitName_ThrowsUnitNotFoundException()
[Fact]
public void FromUnitAbbreviation_ReturnsQuantity()
{
- IQuantity q = Quantity.FromUnitAbbreviation(5, "cm");
+ IQuantity q = Quantity.FromUnitAbbreviation(CultureInfo.InvariantCulture, 5, "cm");
Assert.Equal(5, q.Value);
Assert.Equal(LengthUnit.Centimeter, q.Unit);
}
@@ -161,16 +158,16 @@ public void FromUnitAbbreviation_ReturnsQuantity()
[Fact]
public void TryFromUnitAbbreviation_ReturnsQuantity()
{
- Assert.True(Quantity.TryFromUnitAbbreviation(5, "cm", out IQuantity? q));
- Assert.Equal(LengthUnit.Centimeter, q!.Unit);
+ Assert.True(Quantity.TryFromUnitAbbreviation(5, "cm", out IQuantity? quantity));
+ Assert.Equal(LengthUnit.Centimeter, quantity!.Unit);
}
[Fact]
public void FromUnitAbbreviation_MatchingCulture_ReturnsQuantity()
{
- IQuantity q = Quantity.FromUnitAbbreviation(Russian, 5, "см");
- Assert.Equal(5, q.Value);
- Assert.Equal(LengthUnit.Centimeter, q.Unit);
+ IQuantity quantity = Quantity.FromUnitAbbreviation(Russian, 5, "см");
+ Assert.Equal(5, quantity.Value);
+ Assert.Equal(LengthUnit.Centimeter, quantity.Unit);
}
[Fact]
diff --git a/UnitsNet.Tests/QuantityTypeConverterTest.cs b/UnitsNet.Tests/QuantityTypeConverterTest.cs
index ca15b50c97..13ba43058d 100644
--- a/UnitsNet.Tests/QuantityTypeConverterTest.cs
+++ b/UnitsNet.Tests/QuantityTypeConverterTest.cs
@@ -1,12 +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;
using System.ComponentModel;
using System.Globalization;
using System.Reflection;
+using UnitsNet.Tests.CustomQuantities;
using UnitsNet.Tests.Helpers;
-using Xunit;
namespace UnitsNet.Tests
{
@@ -122,6 +121,53 @@ public void ConvertFrom_GivenQuantityStringAndContextWithDefaultUnitAndConvertTo
Assert.Equal(expectedUnit, convertedValue.Unit);
}
+ [Theory]
+ [InlineData(1.234)]
+ [InlineData(-1.234)]
+ [InlineData(double.NaN)]
+ [InlineData(double.PositiveInfinity)]
+ [InlineData(double.NegativeInfinity)]
+ public void ConvertFrom_GivenQuantityStringAndNullCulture_ReturnsQuantityConvertedToUnit(double expectedValue)
+ {
+ var str = expectedValue.ToString(CultureInfo.CurrentCulture) + "mm";
+ var converter = new QuantityTypeConverter();
+
+ var convertedValue = (Length)converter.ConvertFrom(null, null, str)!;
+
+ Assert.Equal(expectedValue, convertedValue.Value);
+ Assert.Equal(LengthUnit.Millimeter, convertedValue.Unit);
+ }
+
+ [Fact]
+ public void ConvertFrom_WithUnknownQuantity_ThrowsQuantityNotFoundException()
+ {
+ var converter = new QuantityTypeConverter();
+ ITypeDescriptorContext context = new TypeDescriptorContext("SomeMemberName", new Attribute[] { });
+
+ Assert.Throws(() => converter.ConvertFrom(context, Culture, "42 st"));
+ }
+
+ [Fact]
+ public void ConvertFrom_WithUnknownUnit_ThrowsUnitNotFoundException()
+ {
+ var converter = new QuantityTypeConverter();
+ ITypeDescriptorContext context = new TypeDescriptorContext("SomeMemberName", new Attribute[]
+ {
+ new DefaultUnitAttribute(HowMuchUnit.Some)
+ });
+
+ Assert.Throws(() => converter.ConvertFrom(context, Culture, "42"));
+ }
+
+ [Fact]
+ public void ConvertFrom_GivenUnsupportedValueType_ThrowsNotSupportedException()
+ {
+ var converter = new QuantityTypeConverter();
+ ITypeDescriptorContext context = new TypeDescriptorContext("SomeMemberName", new Attribute[] { });
+
+ Assert.Throws(() => converter.ConvertFrom(context, Culture, DateTime.Now));
+ }
+
[Fact]
public void ConvertFrom_GivenEmptyString_ThrowsNotSupportedException()
{
@@ -132,12 +178,12 @@ public void ConvertFrom_GivenEmptyString_ThrowsNotSupportedException()
}
[Fact]
- public void ConvertFrom_GivenWrongQuantity_ThrowsUnitNotFoundException()
+ public void ConvertFrom_GivenWrongQuantityStringFormat_ThrowsFormatException()
{
var converter = new QuantityTypeConverter();
ITypeDescriptorContext context = new TypeDescriptorContext("SomeMemberName", new Attribute[] { });
- Assert.Throws(() => converter.ConvertFrom(context, Culture, "1m^2"));
+ Assert.Throws(() => converter.ConvertFrom(context, Culture, "1 meter"));
}
[Theory]
diff --git a/UnitsNet.Tests/UnitInfoTests.cs b/UnitsNet.Tests/UnitInfoTests.cs
index e05e3a51f9..1b428c442d 100644
--- a/UnitsNet.Tests/UnitInfoTests.cs
+++ b/UnitsNet.Tests/UnitInfoTests.cs
@@ -1,27 +1,125 @@
// 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 UnitsNet.Units;
-using Xunit;
+namespace UnitsNet.Tests;
-namespace UnitsNet.Tests
+public class UnitInfoTests
{
- public class UnitInfoTests
+ [Fact]
+ public void UnitInfo_QuantityInfo_ReturnsTheParentQuantityInfo()
{
- [Fact]
- public void ConstructorTest()
+ Assert.Multiple(() =>
{
- var unitInfo = new UnitInfo(LengthUnit.Meter, "Meters", new BaseUnits(LengthUnit.Meter), nameof(Length));
- Assert.Equal(LengthUnit.Meter, unitInfo.Value);
- Assert.Equal(LengthUnit.Meter.ToString(), unitInfo.Name);
- }
+ UnitInfo unitInfo = Mass.Info.BaseUnitInfo;
- [Fact]
- public void GenericConstructorTest()
+ QuantityInfo quantityInfo = unitInfo.QuantityInfo;
+
+ Assert.Equal(Mass.Info, quantityInfo);
+ }, () =>
+ {
+ UnitInfo unitInfo = Mass.Info.BaseUnitInfo;
+
+ QuantityInfo quantityInfo = unitInfo.QuantityInfo;
+
+ Assert.Equal(Mass.Info, quantityInfo);
+ });
+ }
+
+ [Fact]
+ public void UnitInfo_QuantityName_ReturnsTheParentQuantityName()
+ {
+ Assert.Equal(Mass.Info.Name, Mass.Info.BaseUnitInfo.QuantityName);
+ }
+
+ [Fact]
+ public void UnitInfo_Value_ReturnsTheUnitValue()
+ {
+ Assert.Multiple(() =>
+ {
+ UnitInfo unitInfo = Mass.Info.BaseUnitInfo;
+
+ MassUnit unitInfoValue = unitInfo.Value;
+
+ Assert.Equal(Mass.BaseUnit, unitInfoValue);
+ }, () =>
+ {
+ UnitInfo unitInfo = Mass.Info.BaseUnitInfo;
+
+ MassUnit unitInfoValue = unitInfo.Value;
+
+ Assert.Equal(Mass.BaseUnit, unitInfoValue);
+ }, () =>
+ {
+ UnitInfo unitInfo = Mass.Info.BaseUnitInfo;
+
+ Enum unitInfoValue = unitInfo.Value;
+
+ Assert.Equal(Mass.BaseUnit, unitInfoValue);
+ });
+ }
+
+ [Fact]
+ public void UnitInfo_UnitKey_ReturnsTheUnitKey()
+ {
+ Assert.Multiple(() =>
+ {
+ UnitInfo unitInfo = Mass.Info.BaseUnitInfo;
+
+ UnitKey unitInfoValue = unitInfo.UnitKey;
+
+ Assert.Equal(Mass.BaseUnit, unitInfoValue);
+ }, () =>
+ {
+ UnitInfo unitInfo = Mass.Info.BaseUnitInfo;
+
+ UnitKey unitInfoValue = unitInfo.UnitKey;
+
+ Assert.Equal(Mass.BaseUnit, unitInfoValue);
+ }, () =>
+ {
+ UnitInfo unitInfo = Mass.Info.BaseUnitInfo;
+
+ UnitKey unitInfoValue = unitInfo.UnitKey;
+
+ Assert.Equal(Mass.BaseUnit, unitInfoValue);
+ });
+ }
+
+ [Theory]
+ [InlineData(1, MassUnit.Kilogram)]
+ [InlineData(2, MassUnit.Milligram)]
+ public void UnitInfo_FromValueAndUnit_ReturnsTheExpectedQuantity(double value, MassUnit unit)
+ {
+ var expectedQuantity = new Mass(value, unit);
+ Assert.Multiple(() =>
+ {
+ UnitInfo unitInfo = Mass.Info[unit];
+
+ Mass quantity = unitInfo.From(value);
+
+ Assert.Equal(expectedQuantity, quantity);
+ }, () =>
+ {
+ UnitInfo unitInfo = Mass.Info[unit];
+
+ IQuantity quantity = unitInfo.From(value);
+
+ Assert.Equal(expectedQuantity, quantity);
+ }, () =>
{
- var unitInfo = new UnitInfo(LengthUnit.Meter, "Meters", new BaseUnits(LengthUnit.Meter), nameof(Length));
- Assert.Equal(LengthUnit.Meter, unitInfo.Value);
- Assert.Equal(LengthUnit.Meter.ToString(), unitInfo.Name);
- }
+ UnitInfo unitInfo = Mass.Info[unit];
+
+ IQuantity quantity = unitInfo.From(value);
+
+ Assert.Equal(expectedQuantity, quantity);
+ });
+ }
+
+ [Fact]
+ public void ToString_ReturnsTheUnitName()
+ {
+ UnitInfo unitInfo = Mass.Info.BaseUnitInfo;
+
+ Assert.Equal(unitInfo.Name, unitInfo.ToString());
}
}
diff --git a/UnitsNet.Tests/UnitParserTests.cs b/UnitsNet.Tests/UnitParserTests.cs
index 63131e4483..de3fa48a26 100644
--- a/UnitsNet.Tests/UnitParserTests.cs
+++ b/UnitsNet.Tests/UnitParserTests.cs
@@ -1,11 +1,8 @@
// 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;
using System.Globalization;
using UnitsNet.Tests.CustomQuantities;
-using UnitsNet.Units;
-using Xunit;
namespace UnitsNet.Tests
{
@@ -92,6 +89,12 @@ public void Parse_NullAbbreviation_Throws_ArgumentNullException()
Assert.Throws(() => UnitsNetSetup.Default.UnitParser.Parse(null!, typeof(LengthUnit)));
}
+ [Fact]
+ public void Parse_UnknownUnitTypeThrowsUnitNotFoundException()
+ {
+ Assert.Throws(() => UnitsNetSetup.Default.UnitParser.Parse("something"));
+ }
+
[Fact]
public void Parse_UnknownAbbreviationThrowsUnitNotFoundException()
{
@@ -198,11 +201,17 @@ public void TryParse_WithNullAbbreviation_ReturnsFalse()
Assert.False(success);
}, () =>
{
- var success = unitParser.TryParse(null, [], null, out UnitInfo? _);
+ var success = unitParser.TryParse(null, [], null, out UnitInfo? _);
Assert.False(success);
});
}
+ [Fact]
+ public void TryParse_UnknownUnitType_ReturnsFalse()
+ {
+ Assert.False(UnitsNetSetup.Default.UnitParser.TryParse("something", out StringComparison _));
+ }
+
[Theory]
[InlineData("")]
[InlineData("z^2")]
@@ -217,7 +226,7 @@ public void TryParse_WithAmbiguousUnits_ReturnsFalse()
{
UnitParser unitParser = UnitsNetSetup.Default.UnitParser;
Assert.False(unitParser.TryParse("pt", CultureInfo.InvariantCulture, out LengthUnit _));
- Assert.False(unitParser.TryParse("pt", Length.Info.UnitInfos, CultureInfo.InvariantCulture, out UnitInfo? _));
+ Assert.False(unitParser.TryParse("pt", Length.Info.UnitInfos, CultureInfo.InvariantCulture, out UnitInfo? _));
}
[Theory]
@@ -248,8 +257,7 @@ public void TryGetUnitFromAbbreviation_WithLocalizedUnit_MatchingCulture_Returns
var success = unitParser.TryGetUnitFromAbbreviation("кг", formatProvider, out UnitInfo? unitInfo);
Assert.True(success);
- Assert.NotNull(unitInfo);
- Assert.Equal(MassUnit.Kilogram, unitInfo.Value);
+ Assert.Equal(Mass.Info[MassUnit.Kilogram], unitInfo);
}
[Fact]
@@ -261,8 +269,7 @@ public void TryGetUnitFromAbbreviation_MatchingFallbackCulture_ReturnsTrue()
var success = unitParser.TryGetUnitFromAbbreviation("kg", formatProvider, out UnitInfo? unitInfo);
Assert.True(success);
- Assert.NotNull(unitInfo);
- Assert.Equal(MassUnit.Kilogram, unitInfo.Value);
+ Assert.Equal(Mass.Info[MassUnit.Kilogram], unitInfo);
}
[Fact]
diff --git a/UnitsNet.Tests/UnitsNet.Tests.csproj b/UnitsNet.Tests/UnitsNet.Tests.csproj
index d23783c60f..1e2a8c7f2f 100644
--- a/UnitsNet.Tests/UnitsNet.Tests.csproj
+++ b/UnitsNet.Tests/UnitsNet.Tests.csproj
@@ -3,9 +3,11 @@
net8.0;net9.0
latest
+ enable
true
CS0618
enable
+ xunit
@@ -36,4 +38,9 @@
+
+
+
+
+
diff --git a/UnitsNet/CustomCode/Quantity.cs b/UnitsNet/CustomCode/Quantity.cs
index d606ea55da..abc4e309e8 100644
--- a/UnitsNet/CustomCode/Quantity.cs
+++ b/UnitsNet/CustomCode/Quantity.cs
@@ -1,44 +1,41 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
-using UnitsNet.Units;
+using System.Globalization;
namespace UnitsNet
{
- public partial class Quantity
+ public static partial class Quantity
{
private static QuantityInfoLookup Quantities => UnitsNetSetup.Default.QuantityInfoLookup;
+ private static QuantityParser QuantityParser => UnitsNetSetup.Default.QuantityParser;
private static UnitParser UnitParser => UnitsNetSetup.Default.UnitParser;
///
- /// All quantity names of , such as "Length" and "Mass".
+ /// All quantity names, such as "Length" and "Mass", that are present in the configuration.
///
public static IReadOnlyCollection Names => Quantities.Names;
///
- /// All quantity information objects, such as and .
+ /// All quantity information objects, such as and , that are present in the configuration.
///
public static IReadOnlyList Infos => Quantities.Infos;
-
+
///
- /// Get for a given unit enum value.
+ /// All QuantityInfo instances mapped by quantity name that are present in the configuration.
///
- public static UnitInfo GetUnitInfo(Enum unitEnum) => Quantities.GetUnitInfo(unitEnum);
+ public static IReadOnlyDictionary ByName => Quantities.ByName;
///
- /// Try to get for a given unit enum value.
+ /// Get for a given unit enum value.
///
- public static bool TryGetUnitInfo(Enum unitEnum, [NotNullWhen(true)] out UnitInfo? unitInfo) =>
- Quantities.TryGetUnitInfo(unitEnum, out unitInfo);
+ public static UnitInfo GetUnitInfo(UnitKey unitEnum) => Quantities.GetUnitInfo(unitEnum);
///
- ///
+ /// Try to get for a given unit enum value.
///
- ///
- ///
- public static void AddUnitInfo(Enum unit, UnitInfo unitInfo) => Quantities.AddUnitInfo(unitInfo);
-
+ public static bool TryGetUnitInfo(UnitKey unitEnum, [NotNullWhen(true)] out UnitInfo? unitInfo)
+ {
+ return Quantities.TryGetUnitInfo(unitEnum, out unitInfo);
+ }
+
///
/// Dynamically constructs a quantity from a numeric value and a unit enum value.
///
@@ -46,11 +43,9 @@ public static bool TryGetUnitInfo(Enum unitEnum, [NotNullWhen(true)] out UnitInf
/// Unit enum value.
/// An object.
/// Unit value is not a known unit enum type.
- public static IQuantity From(double value, Enum unit)
+ public static IQuantity From(double value, UnitKey unit)
{
- return TryFrom(value, unit, out IQuantity? quantity)
- ? quantity
- : throw new UnitNotFoundException($"Unit value {unit} of type {unit.GetType()} is not a known unit enum type. Expected types like UnitsNet.Units.LengthUnit. Did you pass in a custom enum type defined outside the UnitsNet library?");
+ return Quantities.From(value, unit);
}
///
@@ -68,7 +63,26 @@ public static IQuantity From(double value, Enum unit)
///
public static IQuantity From(double value, string quantityName, string unitName)
{
- return From(value, Quantities.GetUnitByName(quantityName, unitName).Value);
+ return Quantities.GetUnitByName(quantityName, unitName).From(value);
+ }
+
+ ///
+ /// Dynamically constructs a quantity of the given with the value in the quantity's base
+ /// units.
+ ///
+ /// The of the quantity to create.
+ /// The value to construct the quantity with.
+ /// The created quantity.
+ ///
+ /// This is the equivalent to:
+ /// quantityInfo.From(value, quantityInfo.BaseUnitInfo.Value)
+ /// or
+ /// quantityInfo.BaseUnitInfo.From(value)
+ ///
+ [Obsolete("Consider using: quantityInfo.BaseUnitInfo.From(value)")]
+ public static IQuantity FromQuantityInfo(QuantityInfo quantityInfo, double value)
+ {
+ return quantityInfo.BaseUnitInfo.From(value);
}
///
@@ -79,7 +93,7 @@ public static IQuantity From(double value, string quantityName, string unitName)
/// Unit abbreviation matching is case-insensitive.
///
/// This will fail if more than one unit across all quantities share the same unit abbreviation.
- /// Prefer or instead.
+ /// Prefer or instead.
///
/// Numeric value.
/// Unit abbreviation, such as "kg" for .
@@ -96,7 +110,7 @@ public static IQuantity From(double value, string quantityName, string unitName)
/// Unit abbreviation matching is case-insensitive.
///
/// This will fail if more than one unit across all quantities share the same unit abbreviation.
- /// Prefer or instead.
+ /// Prefer or instead.
///
/// The format provider to use for lookup. Defaults to if null.
/// Numeric value.
@@ -106,7 +120,7 @@ public static IQuantity From(double value, string quantityName, string unitName)
/// Multiple units found matching the given unit abbreviation.
public static IQuantity FromUnitAbbreviation(IFormatProvider? formatProvider, double value, string unitAbbreviation)
{
- return From(value, UnitParser.GetUnitFromAbbreviation(unitAbbreviation, formatProvider).Value);
+ return UnitParser.FromUnitAbbreviation(value, unitAbbreviation, formatProvider);
}
///
@@ -119,13 +133,31 @@ public static IQuantity FromUnitAbbreviation(IFormatProvider? formatProvider, do
/// True if successful with assigned the value, otherwise false.
public static bool TryFrom(double value, string quantityName, string unitName, [NotNullWhen(true)] out IQuantity? quantity)
{
- if (Quantities.TryGetUnitByName(quantityName, unitName, out UnitInfo? unitInfo))
+ if (!Quantities.TryGetUnitByName(quantityName, unitName, out UnitInfo? unitInfo))
{
- return TryFrom(value, unitInfo.Value, out quantity);
+ quantity = null;
+ return false;
}
-
- quantity = null;
- return false;
+
+ quantity = unitInfo.From(value);
+ return true;
+ }
+
+ ///
+ /// Attempts to create a quantity from the specified value and unit.
+ ///
+ /// The value of the quantity.
+ /// The unit of the quantity, represented as an .
+ ///
+ /// When this method returns, contains the created quantity if the conversion succeeded,
+ /// or null if the conversion failed. This parameter is passed uninitialized.
+ ///
+ ///
+ /// true if the quantity was successfully created; otherwise, false.
+ ///
+ public static bool TryFrom(double value, Enum? unit, [NotNullWhen(true)] out IQuantity? quantity)
+ {
+ return Quantities.TryFrom(value, unit, out quantity);
}
///
@@ -136,7 +168,7 @@ public static bool TryFrom(double value, string quantityName, string unitName, [
/// Unit abbreviation matching is case-insensitive.
///
/// This will fail if more than one unit across all quantities share the same unit abbreviation.
- /// Prefer or instead.
+ /// Prefer or instead.
///
/// Numeric value.
/// Unit abbreviation, such as "kg" for .
@@ -154,7 +186,7 @@ public static bool TryFromUnitAbbreviation(double value, string unitAbbreviation
/// Unit abbreviation matching is case-insensitive.
///
/// This will fail if more than one unit across all quantities share the same unit abbreviation.
- /// Prefer or instead.
+ /// Prefer or instead.
///
/// The format provider to use for lookup. Defaults to if null.
/// Numeric value.
@@ -166,7 +198,8 @@ public static bool TryFromUnitAbbreviation(IFormatProvider? formatProvider, doub
{
if (UnitParser.TryGetUnitFromAbbreviation(unitAbbreviation, formatProvider, out UnitInfo? unitInfo))
{
- return TryFrom(value, unitInfo.Value, out quantity);
+ quantity = unitInfo.From(value);
+ return true;
}
quantity = null;
@@ -183,27 +216,37 @@ public static bool TryFromUnitAbbreviation(IFormatProvider? formatProvider, doub
/// Type of quantity, such as .
/// Quantity string representation, such as "1.5 kg". Must be compatible with given quantity type.
/// The parsed quantity.
- /// Type must be of type UnitsNet.IQuantity -or- Type is not a known quantity type.
- /// Type must be of type UnitsNet.IQuantity -or- Type is not a known quantity type.
+ ///
+ /// Thrown when the is not of type .
+ ///
+ ///
+ /// Thrown when the specified quantity type is not registered in the current configuration.
+ ///
+ /// Thrown when the is not in the expected format.
public static IQuantity Parse(IFormatProvider? formatProvider, Type quantityType, string quantityString)
{
- // TODO Support custom units (via the QuantityParser), currently only hardcoded built-in quantities are supported.
- if (!typeof(IQuantity).IsAssignableFrom(quantityType))
- throw new ArgumentException($"Type {quantityType} must be of type UnitsNet.IQuantity.");
-
- if (TryParse(formatProvider, quantityType, quantityString, out IQuantity? quantity))
- return quantity;
-
- throw new UnitNotFoundException($"Quantity string '{quantityString}' could not be parsed to quantity '{quantityType}'.");
+ QuantityInfo quantityInfo = Quantities.GetQuantityInfo(quantityType);
+ return QuantityParser.Parse(quantityString, formatProvider, quantityInfo);
}
///
public static bool TryParse(Type quantityType, string quantityString, [NotNullWhen(true)] out IQuantity? quantity)
{
- // TODO Support custom units (via the QuantityParser), currently only hardcoded built-in quantities are supported.
return TryParse(null, quantityType, quantityString, out quantity);
}
+ ///
+ public static bool TryParse(IFormatProvider? formatProvider, Type quantityType, string quantityString, [NotNullWhen(true)] out IQuantity? quantity)
+ {
+ if (Quantities.TryGetQuantityInfo(quantityType, out QuantityInfo? quantityInfo))
+ {
+ return QuantityParser.TryParse(quantityString, formatProvider, quantityInfo, out quantity);
+ }
+
+ quantity = null;
+ return false;
+ }
+
///
/// Get a list of quantities that has the given base dimensions.
///
diff --git a/UnitsNet/CustomCode/QuantityInfo/QuantityInfoExtensions.cs b/UnitsNet/CustomCode/QuantityInfo/QuantityInfoExtensions.cs
index 8d74808c67..e8b93c6d20 100644
--- a/UnitsNet/CustomCode/QuantityInfo/QuantityInfoExtensions.cs
+++ b/UnitsNet/CustomCode/QuantityInfo/QuantityInfoExtensions.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using UnitsNet.Units;
namespace UnitsNet;
@@ -24,6 +25,62 @@ public static IEnumerable GetQuantitiesWithBaseDimensions(this IEn
return quantityInfos.Where(info => info.BaseDimensions.Equals(baseDimensions));
}
+
+ ///
+ /// Filters a collection of unit information based on the specified base units.
+ ///
+ /// The type of the unit information.
+ /// The collection of unit information to filter.
+ /// The base units to filter by.
+ /// An containing the unit information that matches the specified base units.
+ /// Thrown when is null.
+ public static IEnumerable GetUnitInfosFor(this IEnumerable unitInfos, BaseUnits baseUnits)
+ where TUnitInfo : UnitInfo
+ {
+ if (baseUnits is null)
+ {
+ throw new ArgumentNullException(nameof(baseUnits));
+ }
+
+ return unitInfos.Where(unitInfo => unitInfo.BaseUnits.IsSubsetOf(baseUnits));
+ }
+
+ ///
+ /// Gets the whose is a subset of .
+ ///
+ ///
+ /// Length.Info.GetUnitInfoFor(unitSystemWithFootAsLengthUnit) returns for
+ /// .
+ ///
+ /// The collection of unit information to filter.
+ /// The to check against.
+ ///
+ /// The that has that is a subset of
+ /// .
+ ///
+ /// is null.
+ /// No unit was found that is a subset of .
+ ///
+ /// More than one unit was found that is a subset of
+ /// .
+ ///
+ public static TUnitInfo GetUnitInfoFor(this IEnumerable unitInfos, BaseUnits baseUnits)
+ where TUnitInfo : UnitInfo
+ {
+ using IEnumerator enumerator = unitInfos.GetUnitInfosFor(baseUnits).GetEnumerator();
+ if (!enumerator.MoveNext())
+ {
+ throw new InvalidOperationException($"No unit was found that is a subset of {nameof(baseUnits)}");
+ }
+
+ TUnitInfo firstUnitInfo = enumerator.Current!;
+ if (enumerator.MoveNext())
+ {
+ throw new InvalidOperationException($"More than one unit was found that is a subset of {nameof(baseUnits)}");
+ }
+
+ return firstUnitInfo;
+ }
///
/// Retrieves the default unit for a specified quantity and unit system.
diff --git a/UnitsNet/CustomCode/QuantityInfo/Units/UnitDefinition.cs b/UnitsNet/CustomCode/QuantityInfo/Units/UnitDefinition.cs
new file mode 100644
index 0000000000..4919be5115
--- /dev/null
+++ b/UnitsNet/CustomCode/QuantityInfo/Units/UnitDefinition.cs
@@ -0,0 +1,64 @@
+// 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;
+using System.Diagnostics;
+using UnitsNet.Units;
+
+namespace UnitsNet;
+
+///
+[DebuggerDisplay("{Name} ({Value})")]
+public sealed class UnitDefinition : IUnitDefinition
+ where TUnit : struct, Enum
+{
+ ///
+ /// Initializes a new instance of the class for the base unit.
+ ///
+ /// The enum value for this unit, for example .
+ /// The plural name of the unit, such as "Centimeters".
+ /// The for this unit.
+ public UnitDefinition(TUnit value, string pluralName, BaseUnits baseUnits)
+ : this(value, value.ToString(), pluralName, baseUnits)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The enum value representing the unit, for example .
+ /// The singular name of the unit, such as "Centimeter".
+ /// The plural name of the unit, such as "Centimeters".
+ /// The associated with this unit.
+ ///
+ /// Thrown when , , , or
+ /// is null.
+ ///
+ public UnitDefinition(TUnit value, string singularName, string pluralName, BaseUnits baseUnits)
+ {
+ Value = value;
+ Name = singularName ?? throw new ArgumentNullException(nameof(singularName));
+ PluralName = pluralName ?? throw new ArgumentNullException(nameof(pluralName));
+ BaseUnits = baseUnits ?? throw new ArgumentNullException(nameof(baseUnits));
+ }
+
+ ///
+ /// The enum value of the unit, such as .
+ ///
+ public TUnit Value { get; }
+
+ ///
+ /// The singular name of the unit, such as "Centimeter".
+ ///
+ public string Name { get; }
+
+ ///
+ /// The plural name of the unit, such as "Centimeters".
+ ///
+ public string PluralName { get; }
+
+ ///
+ /// Gets the for this unit.
+ ///
+ public BaseUnits BaseUnits { get; }
+}
diff --git a/UnitsNet/CustomCode/QuantityInfo/Units/UnitEqualityComparer.cs b/UnitsNet/CustomCode/QuantityInfo/Units/UnitEqualityComparer.cs
new file mode 100644
index 0000000000..99f99e8c20
--- /dev/null
+++ b/UnitsNet/CustomCode/QuantityInfo/Units/UnitEqualityComparer.cs
@@ -0,0 +1,42 @@
+#if NETSTANDARD2_0
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+namespace UnitsNet;
+
+///
+/// Provides a custom equality comparer for enumerations that represent units.
+///
+/// The enumeration type representing the unit.
+///
+/// This comparer uses the class to convert the enumeration to an
+/// integer,
+/// which is faster than the default equality comparer on .NET Framework. On .NET 8, the performance is comparable.
+///
+internal class UnitEqualityComparer : IEqualityComparer
+ where TUnit : struct, Enum
+{
+ // Singleton instance of the comparer
+ public static readonly UnitEqualityComparer Default = new();
+
+ private UnitEqualityComparer()
+ {
+ }
+
+ public bool Equals(TUnit x, TUnit y)
+ {
+ // Use Unsafe.As to convert enums to integers for comparison
+ var xInt = Unsafe.As(ref x);
+ var yInt = Unsafe.As(ref y);
+ return xInt == yInt;
+ }
+
+ public int GetHashCode(TUnit obj)
+ {
+ // Use Unsafe.As to convert enum to integer for hash code calculation
+ var objInt = Unsafe.As(ref obj);
+ return objInt.GetHashCode();
+ }
+}
+#endif
diff --git a/UnitsNet/CustomCode/QuantityParser.cs b/UnitsNet/CustomCode/QuantityParser.cs
index 4ca6bfde4c..d542a2e59f 100644
--- a/UnitsNet/CustomCode/QuantityParser.cs
+++ b/UnitsNet/CustomCode/QuantityParser.cs
@@ -1,13 +1,9 @@
// 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;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
-using UnitsNet.Units;
// ReSharper disable once CheckNamespace
namespace UnitsNet;
@@ -36,7 +32,7 @@ public class QuantityParser
private const NumberStyles ParseNumberStyles = NumberStyles.Number | NumberStyles.Float | NumberStyles.AllowExponent;
private readonly UnitParser _unitParser;
-
+
///
/// Initializes a new instance of the class using the specified
/// .
@@ -107,6 +103,26 @@ public TQuantity Parse(string str, IFormatProvider? format
return ParseWithRegex(valueString, unitString, fromDelegate, formatProvider);
}
+ ///
+ internal IQuantity Parse(string str, IFormatProvider? formatProvider, QuantityInfo quantityInfo)
+ {
+ if (str == null) throw new ArgumentNullException(nameof(str));
+ str = str.Trim();
+
+ Regex regex = CreateRegexForQuantity(quantityInfo.UnitType, formatProvider);
+
+ if (!TryExtractValueAndUnit(regex, str, out var valueString, out var unitString))
+ {
+ throw new FormatException(
+ "Unable to parse quantity. Expected the form \"{value} {unit abbreviation}\", such as \"5.5 m\". The spacing is optional.")
+ {
+ Data = { ["input"] = str }
+ };
+ }
+
+ return ParseWithRegex(valueString, unitString, quantityInfo.UnitInfos, formatProvider);
+ }
+
///
/// Tries to parse a quantity from a string, such as "1.2 kg" to or "100 cm" to
/// .
@@ -142,47 +158,18 @@ public bool TryParse(string? str, IFormatProvider? formatP
TryParseWithRegex(valueString, unitString, fromDelegate, formatProvider, out result);
}
- ///
- /// Tries to parse a quantity from a string, such as "1.2 kg" to or "100 cm" to
- /// .
- ///
- ///
- /// Similar to
- ///
- /// ,
- /// but returns instead. This is workaround for C# not allowing to pass on 'out' param from
- /// type Length to IQuantity,
- /// even though they are compatible.
- ///
- /// The string to parse, such as "1.2 kg".
- ///
- /// The culture for looking up localized unit abbreviations for a language, and for parsing
- /// the number formatted in this culture. Defaults to .
- ///
- /// A function to create a quantity given a numeric value and a unit enum value.
- /// The parsed quantity if successful, otherwise null.
- /// The type of quantity to create, such as .
- ///
- /// The type of unit enum that belongs to this quantity, such as for
- /// .
- ///
- /// True if successful.
- /// The string was null.
- /// Failed to parse quantity.
- internal bool TryParse(string? str, IFormatProvider? formatProvider, QuantityFromDelegate fromDelegate,
- [NotNullWhen(true)] out IQuantity? result)
- where TQuantity : IQuantity
- where TUnitType : struct, Enum
+ ///
+ internal bool TryParse(string? str, IFormatProvider? formatProvider, QuantityInfo quantityInfo, [NotNullWhen(true)] out IQuantity? result)
{
- if (TryParse(str, formatProvider, fromDelegate, out TQuantity? quantityParsed))
- {
- result = quantityParsed;
- return true;
- }
-
result = null;
- return false;
+
+ if (string.IsNullOrWhiteSpace(str)) return false;
+ str = str!.Trim(); // netstandard2.0 nullable quirk
+
+ Regex regex = CreateRegexForQuantity(quantityInfo.UnitType, formatProvider);
+
+ return TryExtractValueAndUnit(regex, str, out var valueString, out var unitString) &&
+ TryParseWithRegex(valueString, unitString, quantityInfo.UnitInfos, formatProvider, out result);
}
internal string CreateRegexPatternForUnit(TUnitType unit, IFormatProvider? formatProvider, bool matchEntireString = true)
@@ -218,6 +205,17 @@ private TQuantity ParseWithRegex(string valueString, strin
return fromDelegate(value, parsedUnit);
}
+ ///
+ /// Parse a string given a particular regular expression.
+ ///
+ /// Error parsing string.
+ private IQuantity ParseWithRegex(string valueString, string unitString, IReadOnlyList units, IFormatProvider? formatProvider)
+ {
+ var value = double.Parse(valueString, ParseNumberStyles, formatProvider);
+ UnitInfo unitInfo = _unitParser.Parse(unitString, units, formatProvider);
+ return unitInfo.From(value);
+ }
+
///
/// Parse a string given a particular regular expression.
///
@@ -243,6 +241,29 @@ private bool TryParseWithRegex(string? valueString, string
return true;
}
+ ///
+ /// Parse a string given a particular regular expression.
+ ///
+ /// Error parsing string.
+ private bool TryParseWithRegex(string? valueString, string? unitString, IReadOnlyList units, IFormatProvider? formatProvider,
+ [NotNullWhen(true)] out IQuantity? result)
+ {
+ result = null;
+
+ if (!double.TryParse(valueString, ParseNumberStyles, formatProvider, out var value))
+ {
+ return false;
+ }
+
+ if (!_unitParser.TryParse(unitString, units, formatProvider, out UnitInfo? parsedUnit))
+ {
+ return false;
+ }
+
+ result = parsedUnit.From(value);
+ return true;
+ }
+
private static bool TryExtractValueAndUnit(Regex regex, string str, [NotNullWhen(true)] out string? valueString, [NotNullWhen(true)] out string? unitString)
{
Match match = regex.Match(str);
diff --git a/UnitsNet/CustomCode/UnitAbbreviationsCache.cs b/UnitsNet/CustomCode/UnitAbbreviationsCache.cs
index 05c5f21fce..f9819870b8 100644
--- a/UnitsNet/CustomCode/UnitAbbreviationsCache.cs
+++ b/UnitsNet/CustomCode/UnitAbbreviationsCache.cs
@@ -1,14 +1,10 @@
// 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;
using System.Collections.Concurrent;
-using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-using System.Reflection;
using System.Resources;
-using UnitsNet.Units;
using AbbreviationMapKey = System.ValueTuple;
// ReSharper disable once CheckNamespace
@@ -88,9 +84,9 @@ public static UnitAbbreviationsCache CreateDefault()
{
return new UnitAbbreviationsCache();
}
-
+
#region MapUnitToAbbreviation overloads
-
+
///
/// Adds one or more unit abbreviation for the given unit enum value.
/// This is used to dynamically add abbreviations for existing unit enums such as or to extend with third-party unit enums
@@ -114,6 +110,12 @@ public void MapUnitToAbbreviation(TUnitType unit, params IEnumerable<
/// The unit enum value.
/// The format provider to use for lookup. Defaults to if null.
/// Unit abbreviations to add.
+ ///
+ /// Thrown when the provided type is null.
+ ///
+ ///
+ /// Thrown when the provided type is not an enumeration type.
+ ///
public void MapUnitToAbbreviation(Type unitType, int unitValue, IFormatProvider? formatProvider, params IEnumerable abbreviations)
{
MapUnitToAbbreviation(UnitKey.Create(unitType, unitValue), formatProvider, abbreviations);
@@ -492,20 +494,18 @@ private static AbbreviationMapKey GetAbbreviationMapKey(UnitInfo unitInfo, Cultu
private static List ReadAbbreviationsFromResourceFile(UnitInfo unitInfo, CultureInfo culture)
{
var abbreviationsList = new List();
- // we currently don't have any way of providing external resource dictionaries
- Assembly unitAssembly = unitInfo.UnitKey.UnitEnumType.Assembly;
- if (unitAssembly != typeof(UnitAbbreviationsCache).Assembly)
+ QuantityInfo quantityInfo = unitInfo.QuantityInfo;
+ ResourceManager? resourceManager = quantityInfo.UnitAbbreviations;
+ if (resourceManager is null)
{
return abbreviationsList;
}
-
- var quantityName = unitInfo.QuantityName;
- string resourceName = $"UnitsNet.GeneratedCode.Resources.{quantityName}";
- var resourceManager = new ResourceManager(resourceName, unitAssembly);
var abbreviationsString = resourceManager.GetString(unitInfo.PluralName, culture);
- if(abbreviationsString is not null)
+ if (abbreviationsString is not null)
+ {
abbreviationsList.AddRange(abbreviationsString.Split(','));
+ }
return abbreviationsList;
}
diff --git a/UnitsNet/CustomCode/UnitParser.cs b/UnitsNet/CustomCode/UnitParser.cs
index a27917f70f..b2339e9122 100644
--- a/UnitsNet/CustomCode/UnitParser.cs
+++ b/UnitsNet/CustomCode/UnitParser.cs
@@ -1,13 +1,9 @@
// 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;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Text;
-using UnitsNet.Units;
// ReSharper disable once CheckNamespace
namespace UnitsNet;
@@ -36,7 +32,7 @@ internal UnitParser(QuantityInfoLookup quantitiesLookup)
: this(new UnitAbbreviationsCache(quantitiesLookup))
{
}
-
+
///
/// Initializes a new instance of the class using the specified unit abbreviations cache.
///
@@ -93,7 +89,9 @@ public static UnitParser CreateDefault()
///
/// The format provider to use for lookup. Defaults to if null.
///
- ///
+ /// Unit enum value, such as .
+ /// No quantity found matching the unit type.
+ /// No units match the abbreviation.
public TUnitType Parse(string unitAbbreviation, IFormatProvider? formatProvider = null)
where TUnitType : struct, Enum
{
@@ -114,6 +112,9 @@ public TUnitType Parse(string unitAbbreviation, IFormatProvider? form
/// Unit enum type, such as and .
/// The format provider to use for lookup. Defaults to if null.
/// Unit enum value, such as .
+ /// The or the is null.
+ /// The is not a valid enumeration type.
+ /// No quantity found matching the unit type.
/// No units match the abbreviation.
/// More than one unit matches the abbreviation.
public Enum Parse(string unitAbbreviation, Type unitType, IFormatProvider? formatProvider = null)
@@ -586,4 +587,25 @@ public bool TryGetUnitFromAbbreviation([NotNullWhen(true)]string? unitAbbreviati
return unitAbbreviationsPairs;
}
+
+ ///
+ /// Dynamically construct a quantity from a numeric value and a unit abbreviation.
+ ///
+ ///
+ /// This method is currently not optimized for performance and will enumerate all units and their unit abbreviations
+ /// each time.
+ /// Unit abbreviation matching in the overload is case-insensitive.
+ ///
+ /// This will fail if more than one unit across all quantities share the same unit abbreviation.
+ ///
+ /// Numeric value.
+ /// Unit abbreviation, such as "kg" for .
+ /// The format provider to use for lookup. Defaults to if null.
+ /// An object.
+ /// Unit abbreviation is not known.
+ /// Multiple units found matching the given unit abbreviation.
+ internal IQuantity FromUnitAbbreviation(double value, string unitAbbreviation, IFormatProvider? formatProvider)
+ {
+ return GetUnitFromAbbreviation(unitAbbreviation, formatProvider).From(value);
+ }
}
diff --git a/UnitsNet/CustomCode/UnitsNetSetup.cs b/UnitsNet/CustomCode/UnitsNetSetup.cs
index 6533fa4244..cb45d2063b 100644
--- a/UnitsNet/CustomCode/UnitsNetSetup.cs
+++ b/UnitsNet/CustomCode/UnitsNetSetup.cs
@@ -21,8 +21,9 @@ public sealed class UnitsNetSetup
{
static UnitsNetSetup()
{
+ IReadOnlyCollection quantityInfos = Quantity.Provider.DefaultQuantities;
+ // note: in order to support the ConvertByAbbreviation, the unit converter should require a UnitParser in the constructor
var unitConverter = UnitConverter.CreateDefault();
- IReadOnlyCollection quantityInfos = Quantity.ByName.Values.ToList();
Default = new UnitsNetSetup(quantityInfos, unitConverter);
}
diff --git a/UnitsNet/GeneratedCode/Quantities/AbsorbedDoseOfIonizingRadiation.g.cs b/UnitsNet/GeneratedCode/Quantities/AbsorbedDoseOfIonizingRadiation.g.cs
index 57cfee1b8d..fb23350f7b 100644
--- a/UnitsNet/GeneratedCode/Quantities/AbsorbedDoseOfIonizingRadiation.g.cs
+++ b/UnitsNet/GeneratedCode/Quantities/AbsorbedDoseOfIonizingRadiation.g.cs
@@ -17,13 +17,9 @@
// 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;
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
using System.Globalization;
-using System.Linq;
+using System.Resources;
using System.Runtime.Serialization;
-using UnitsNet.Units;
#if NET
using System.Numerics;
#endif
@@ -66,34 +62,85 @@ namespace UnitsNet
[DataMember(Name = "Unit", Order = 2)]
private readonly AbsorbedDoseOfIonizingRadiationUnit? _unit;
- static AbsorbedDoseOfIonizingRadiation()
+ ///
+ /// Provides detailed information about the quantity, including its name, base unit, unit mappings, base dimensions, and conversion functions.
+ ///
+ public sealed class AbsorbedDoseOfIonizingRadiationInfo: QuantityInfo
{
- BaseDimensions = new BaseDimensions(2, 0, -2, 0, 0, 0, 0);
- BaseUnit = AbsorbedDoseOfIonizingRadiationUnit.Gray;
- Units = Enum.GetValues(typeof(AbsorbedDoseOfIonizingRadiationUnit)).Cast().ToArray();
- Zero = new AbsorbedDoseOfIonizingRadiation(0, BaseUnit);
- Info = new QuantityInfo("AbsorbedDoseOfIonizingRadiation",
- new UnitInfo[]
- {
- new UnitInfo(AbsorbedDoseOfIonizingRadiationUnit.Centigray, "Centigrays", new BaseUnits(length: LengthUnit.Decimeter, time: DurationUnit.Second), "AbsorbedDoseOfIonizingRadiation"),
- new UnitInfo(AbsorbedDoseOfIonizingRadiationUnit.Femtogray, "Femtograys", BaseUnits.Undefined, "AbsorbedDoseOfIonizingRadiation"),
- new UnitInfo(AbsorbedDoseOfIonizingRadiationUnit.Gigagray, "Gigagrays", BaseUnits.Undefined, "AbsorbedDoseOfIonizingRadiation"),
- new UnitInfo(AbsorbedDoseOfIonizingRadiationUnit.Gray, "Grays", new BaseUnits(length: LengthUnit.Meter, time: DurationUnit.Second), "AbsorbedDoseOfIonizingRadiation"),
- new UnitInfo(AbsorbedDoseOfIonizingRadiationUnit.Kilogray, "Kilograys", BaseUnits.Undefined, "AbsorbedDoseOfIonizingRadiation"),
- new UnitInfo(AbsorbedDoseOfIonizingRadiationUnit.Kilorad, "Kilorads", BaseUnits.Undefined, "AbsorbedDoseOfIonizingRadiation"),
- new UnitInfo(AbsorbedDoseOfIonizingRadiationUnit.Megagray, "Megagrays", new BaseUnits(length: LengthUnit.Kilometer, time: DurationUnit.Second), "AbsorbedDoseOfIonizingRadiation"),
- new UnitInfo(AbsorbedDoseOfIonizingRadiationUnit.Megarad, "Megarads", BaseUnits.Undefined, "AbsorbedDoseOfIonizingRadiation"),
- new UnitInfo(AbsorbedDoseOfIonizingRadiationUnit.Microgray, "Micrograys", new BaseUnits(length: LengthUnit.Millimeter, time: DurationUnit.Second), "AbsorbedDoseOfIonizingRadiation"),
- new UnitInfo(AbsorbedDoseOfIonizingRadiationUnit.Milligray, "Milligrays", BaseUnits.Undefined, "AbsorbedDoseOfIonizingRadiation"),
- new UnitInfo(AbsorbedDoseOfIonizingRadiationUnit.Millirad, "Millirads", BaseUnits.Undefined, "AbsorbedDoseOfIonizingRadiation"),
- new UnitInfo(AbsorbedDoseOfIonizingRadiationUnit.Nanogray, "Nanograys", BaseUnits.Undefined, "AbsorbedDoseOfIonizingRadiation"),
- new UnitInfo(AbsorbedDoseOfIonizingRadiationUnit.Petagray, "Petagrays", BaseUnits.Undefined, "AbsorbedDoseOfIonizingRadiation"),
- new UnitInfo(AbsorbedDoseOfIonizingRadiationUnit.Picogray, "Picograys", new BaseUnits(length: LengthUnit.Micrometer, time: DurationUnit.Second), "AbsorbedDoseOfIonizingRadiation"),
- new UnitInfo(AbsorbedDoseOfIonizingRadiationUnit.Rad, "Rads", BaseUnits.Undefined, "AbsorbedDoseOfIonizingRadiation"),
- new UnitInfo(AbsorbedDoseOfIonizingRadiationUnit.Teragray, "Teragrays", new BaseUnits(length: LengthUnit.Megameter, time: DurationUnit.Second), "AbsorbedDoseOfIonizingRadiation"),
- },
- BaseUnit, Zero, BaseDimensions);
+ ///
+ public AbsorbedDoseOfIonizingRadiationInfo(string name, AbsorbedDoseOfIonizingRadiationUnit baseUnit, IEnumerable> unitMappings, AbsorbedDoseOfIonizingRadiation zero, BaseDimensions baseDimensions,
+ QuantityFromDelegate fromDelegate, ResourceManager? unitAbbreviations)
+ : base(name, baseUnit, unitMappings, zero, baseDimensions, fromDelegate, unitAbbreviations)
+ {
+ }
+
+ ///
+ public AbsorbedDoseOfIonizingRadiationInfo(string name, AbsorbedDoseOfIonizingRadiationUnit baseUnit, IEnumerable> unitMappings, AbsorbedDoseOfIonizingRadiation zero, BaseDimensions baseDimensions)
+ : this(name, baseUnit, unitMappings, zero, baseDimensions, AbsorbedDoseOfIonizingRadiation.From, new ResourceManager("UnitsNet.GeneratedCode.Resources.AbsorbedDoseOfIonizingRadiation", typeof(AbsorbedDoseOfIonizingRadiation).Assembly))
+ {
+ }
+
+ ///
+ /// Creates a new instance of the class with the default settings for the AbsorbedDoseOfIonizingRadiation quantity.
+ ///
+ /// A new instance of the class with the default settings.
+ public static AbsorbedDoseOfIonizingRadiationInfo CreateDefault()
+ {
+ return new AbsorbedDoseOfIonizingRadiationInfo(nameof(AbsorbedDoseOfIonizingRadiation), DefaultBaseUnit, GetDefaultMappings(), new AbsorbedDoseOfIonizingRadiation(0, DefaultBaseUnit), DefaultBaseDimensions);
+ }
+ ///
+ /// Creates a new instance of the class with the default settings for the AbsorbedDoseOfIonizingRadiation quantity and a callback for customizing the default unit mappings.
+ ///
+ ///
+ /// A callback function for customizing the default unit mappings.
+ ///
+ ///
+ /// A new instance of the class with the default settings.
+ ///
+ public static AbsorbedDoseOfIonizingRadiationInfo CreateDefault(Func>, IEnumerable>> customizeUnits)
+ {
+ return new AbsorbedDoseOfIonizingRadiationInfo(nameof(AbsorbedDoseOfIonizingRadiation), DefaultBaseUnit, customizeUnits(GetDefaultMappings()), new AbsorbedDoseOfIonizingRadiation(0, DefaultBaseUnit), DefaultBaseDimensions);
+ }
+
+ ///
+ /// The for is [T^-2][L^2].
+ ///
+ public static BaseDimensions DefaultBaseDimensions { get; } = new BaseDimensions(2, 0, -2, 0, 0, 0, 0);
+
+ ///
+ /// The default base unit of AbsorbedDoseOfIonizingRadiation is Gray. All conversions, as defined in the , go via this value.
+ ///
+ public static AbsorbedDoseOfIonizingRadiationUnit DefaultBaseUnit { get; } = AbsorbedDoseOfIonizingRadiationUnit.Gray;
+
+ ///
+ /// Retrieves the default mappings for .
+ ///
+ /// An of representing the default unit mappings for AbsorbedDoseOfIonizingRadiation.
+ public static IEnumerable> GetDefaultMappings()
+ {
+ yield return new (AbsorbedDoseOfIonizingRadiationUnit.Centigray, "Centigray", "Centigrays", new BaseUnits(length: LengthUnit.Decimeter, time: DurationUnit.Second));
+ yield return new (AbsorbedDoseOfIonizingRadiationUnit.Femtogray, "Femtogray", "Femtograys", BaseUnits.Undefined);
+ yield return new (AbsorbedDoseOfIonizingRadiationUnit.Gigagray, "Gigagray", "Gigagrays", BaseUnits.Undefined);
+ yield return new (AbsorbedDoseOfIonizingRadiationUnit.Gray, "Gray", "Grays", new BaseUnits(length: LengthUnit.Meter, time: DurationUnit.Second));
+ yield return new (AbsorbedDoseOfIonizingRadiationUnit.Kilogray, "Kilogray", "Kilograys", BaseUnits.Undefined);
+ yield return new (AbsorbedDoseOfIonizingRadiationUnit.Kilorad, "Kilorad", "Kilorads", BaseUnits.Undefined);
+ yield return new (AbsorbedDoseOfIonizingRadiationUnit.Megagray, "Megagray", "Megagrays", new BaseUnits(length: LengthUnit.Kilometer, time: DurationUnit.Second));
+ yield return new (AbsorbedDoseOfIonizingRadiationUnit.Megarad, "Megarad", "Megarads", BaseUnits.Undefined);
+ yield return new (AbsorbedDoseOfIonizingRadiationUnit.Microgray, "Microgray", "Micrograys", new BaseUnits(length: LengthUnit.Millimeter, time: DurationUnit.Second));
+ yield return new (AbsorbedDoseOfIonizingRadiationUnit.Milligray, "Milligray", "Milligrays", BaseUnits.Undefined);
+ yield return new (AbsorbedDoseOfIonizingRadiationUnit.Millirad, "Millirad", "Millirads", BaseUnits.Undefined);
+ yield return new (AbsorbedDoseOfIonizingRadiationUnit.Nanogray, "Nanogray", "Nanograys", BaseUnits.Undefined);
+ yield return new (AbsorbedDoseOfIonizingRadiationUnit.Petagray, "Petagray", "Petagrays", BaseUnits.Undefined);
+ yield return new (AbsorbedDoseOfIonizingRadiationUnit.Picogray, "Picogray", "Picograys", new BaseUnits(length: LengthUnit.Micrometer, time: DurationUnit.Second));
+ yield return new (AbsorbedDoseOfIonizingRadiationUnit.Rad, "Rad", "Rads", BaseUnits.Undefined);
+ yield return new (AbsorbedDoseOfIonizingRadiationUnit.Teragray, "Teragray", "Teragrays", new BaseUnits(length: LengthUnit.Megameter, time: DurationUnit.Second));
+ }
+ }
+
+ static AbsorbedDoseOfIonizingRadiation()
+ {
+ Info = AbsorbedDoseOfIonizingRadiationInfo.CreateDefault();
DefaultConversionFunctions = new UnitConverter();
RegisterDefaultConversions(DefaultConversionFunctions);
}
@@ -131,27 +178,27 @@ public AbsorbedDoseOfIonizingRadiation(double value, UnitSystem unitSystem)
public static UnitConverter DefaultConversionFunctions { get; }
///
- public static QuantityInfo Info { get; }
+ public static QuantityInfo Info { get; }
///
/// The of this quantity.
///
- public static BaseDimensions BaseDimensions { get; }
+ public static BaseDimensions BaseDimensions => Info.BaseDimensions;
///
/// The base unit of AbsorbedDoseOfIonizingRadiation, which is Gray. All conversions go via this value.
///
- public static AbsorbedDoseOfIonizingRadiationUnit BaseUnit { get; }
+ public static AbsorbedDoseOfIonizingRadiationUnit BaseUnit => Info.BaseUnitInfo.Value;
///
/// All units of measurement for the AbsorbedDoseOfIonizingRadiation quantity.
///
- public static AbsorbedDoseOfIonizingRadiationUnit[] Units { get; }
+ public static IReadOnlyCollection Units => Info.Units;
///
/// Gets an instance of this quantity with a value of 0 in the base unit Gray.
///
- public static AbsorbedDoseOfIonizingRadiation Zero { get; }
+ public static AbsorbedDoseOfIonizingRadiation Zero => Info.Zero;
///
public static AbsorbedDoseOfIonizingRadiation AdditiveIdentity => Zero;
@@ -169,7 +216,7 @@ public AbsorbedDoseOfIonizingRadiation(double value, UnitSystem unitSystem)
public AbsorbedDoseOfIonizingRadiationUnit Unit => _unit.GetValueOrDefault(BaseUnit);
///
- public QuantityInfo QuantityInfo => Info;
+ public QuantityInfo QuantityInfo => Info;
///
/// The of this quantity.
@@ -187,6 +234,9 @@ public AbsorbedDoseOfIonizingRadiation(double value, UnitSystem unitSystem)
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
QuantityInfo IQuantity.QuantityInfo => Info;
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ QuantityInfo IQuantity.QuantityInfo => Info;
+
#endregion
#endregion
diff --git a/UnitsNet/GeneratedCode/Quantities/Acceleration.g.cs b/UnitsNet/GeneratedCode/Quantities/Acceleration.g.cs
index 584ac0de3e..5eafbc6d55 100644
--- a/UnitsNet/GeneratedCode/Quantities/Acceleration.g.cs
+++ b/UnitsNet/GeneratedCode/Quantities/Acceleration.g.cs
@@ -17,13 +17,9 @@
// 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;
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
using System.Globalization;
-using System.Linq;
+using System.Resources;
using System.Runtime.Serialization;
-using UnitsNet.Units;
#if NET
using System.Numerics;
#endif
@@ -70,32 +66,83 @@ namespace UnitsNet
[DataMember(Name = "Unit", Order = 2)]
private readonly AccelerationUnit? _unit;
- static Acceleration()
+ ///
+ /// Provides detailed information about the quantity, including its name, base unit, unit mappings, base dimensions, and conversion functions.
+ ///
+ public sealed class AccelerationInfo: QuantityInfo
{
- BaseDimensions = new BaseDimensions(1, 0, -2, 0, 0, 0, 0);
- BaseUnit = AccelerationUnit.MeterPerSecondSquared;
- Units = Enum.GetValues(typeof(AccelerationUnit)).Cast().ToArray();
- Zero = new Acceleration(0, BaseUnit);
- Info = new QuantityInfo