Skip to content

Commit

Permalink
- QuantityInfoLookup: introduced an array of QuantityInfo and replace…
Browse files Browse the repository at this point in the history
…d the _quantitiesByName into a regular (lazy-loaded) dictionary

- UnitsNetSetup and UnitAbbreviationsCache constructors changed from IReadOnlyCollection<QuantityInfo> into IEnumerable<QuantityInfo>
- changed the Quantity.Infos from IReadOnlyCollection to IReadOnlyList
  • Loading branch information
lipchev committed Feb 7, 2025
1 parent 8e2f897 commit 6dc5f09
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 25 deletions.
6 changes: 3 additions & 3 deletions UnitsNet/CustomCode/Quantity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ public partial class Quantity
private static UnitParser UnitParser => UnitsNetSetup.Default.UnitParser;

/// <summary>
/// All enum value names of <see cref="Infos"/>, such as "Length" and "Mass".
/// All quantity names of <see cref="Infos"/>, such as "Length" and "Mass".
/// </summary>
public static IReadOnlyCollection<string> Names { get => Quantities.Names; }
public static IReadOnlyCollection<string> Names => Quantities.Names;

/// <summary>
/// All quantity information objects, such as <see cref="Length.Info"/> and <see cref="Mass.Info"/>.
/// </summary>
public static IReadOnlyCollection<QuantityInfo> Infos => Quantities.Infos;
public static IReadOnlyList<QuantityInfo> Infos => Quantities.Infos;

/// <summary>
/// Get <see cref="UnitInfo"/> for a given unit enum value.
Expand Down
2 changes: 1 addition & 1 deletion UnitsNet/CustomCode/UnitAbbreviationsCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public UnitAbbreviationsCache()
/// Creates an instance of the cache using the specified set of quantities.
/// </summary>
/// <returns>Instance for mapping the units of the provided quantities.</returns>
public UnitAbbreviationsCache(IReadOnlyCollection<QuantityInfo> quantities)
public UnitAbbreviationsCache(IEnumerable<QuantityInfo> quantities)
:this(new QuantityInfoLookup(quantities))
{
}
Expand Down
2 changes: 1 addition & 1 deletion UnitsNet/CustomCode/UnitsNetSetup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ static UnitsNetSetup()
/// </summary>
/// <param name="quantityInfos">The quantities and their units to support for unit conversions, Parse() and ToString().</param>
/// <param name="unitConverter">The unit converter instance.</param>
public UnitsNetSetup(IReadOnlyCollection<QuantityInfo> quantityInfos, UnitConverter unitConverter)
public UnitsNetSetup(IEnumerable<QuantityInfo> quantityInfos, UnitConverter unitConverter)
{
var quantityInfoLookup = new QuantityInfoLookup(quantityInfos);
var unitAbbreviations = new UnitAbbreviationsCache(quantityInfoLookup);
Expand Down
62 changes: 42 additions & 20 deletions UnitsNet/QuantityInfoLookup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
#if NET8_0_OR_GREATER
using System.Collections.Frozen;
using QuantityByTypeLookupDictionary = System.Collections.Frozen.FrozenDictionary<System.Type, UnitsNet.QuantityInfo>;
using QuantityByNameLookupDictionary = System.Collections.Frozen.FrozenDictionary<string, UnitsNet.QuantityInfo>;
#else
using QuantityByTypeLookupDictionary = System.Collections.Generic.Dictionary<System.Type, UnitsNet.QuantityInfo>;
using QuantityByNameLookupDictionary = System.Collections.Generic.Dictionary<string, UnitsNet.QuantityInfo>;
#endif
using UnitByKeyLookupDictionary = System.Collections.Generic.Dictionary<UnitsNet.UnitKey, UnitsNet.UnitInfo>;

Expand All @@ -20,33 +22,53 @@ namespace UnitsNet;
/// </remarks>
internal class QuantityInfoLookup
{
private readonly Lazy<SortedDictionary<string, QuantityInfo>> _quantitiesByName;
private readonly QuantityInfo[] _quantities;
private readonly Lazy<QuantityByNameLookupDictionary> _quantitiesByName;
private readonly Lazy<QuantityByTypeLookupDictionary> _quantitiesByUnitType;
private readonly Lazy<UnitByKeyLookupDictionary> _unitsByKey;

/// <summary>
/// Initializes a new instance of the <see cref="QuantityInfoLookup" /> class.
/// </summary>
/// <param name="quantityInfos">A collection of quantity information objects.</param>
public QuantityInfoLookup(IReadOnlyCollection<QuantityInfo> quantityInfos)
private QuantityByNameLookupDictionary GroupQuantitiesByName()
{
_quantitiesByName = new Lazy<SortedDictionary<string, QuantityInfo>>(() =>
{
var sortedDictionary = new SortedDictionary<string, QuantityInfo>(StringComparer.OrdinalIgnoreCase);
foreach (QuantityInfo quantityInfo in quantityInfos)
{
sortedDictionary.Add(quantityInfo.Name, quantityInfo);
}

return sortedDictionary;
});
#if NET8_0_OR_GREATER
return _quantities.ToFrozenDictionary(info => info.Name, StringComparer.OrdinalIgnoreCase);
#else
return _quantities.ToDictionary(info => info.Name, StringComparer.OrdinalIgnoreCase);
#endif
}

private QuantityByTypeLookupDictionary GroupQuantitiesByUnitType()
{
#if NET8_0_OR_GREATER
_quantitiesByUnitType = new Lazy<QuantityByTypeLookupDictionary>(() => quantityInfos.ToFrozenDictionary(info => info.UnitType));
return _quantities.ToFrozenDictionary(info => info.UnitType);
#else
_quantitiesByUnitType = new Lazy<QuantityByTypeLookupDictionary>(() => quantityInfos.ToDictionary(info => info.UnitType));
return _quantities.ToDictionary(info => info.UnitType);
#endif
_unitsByKey = new Lazy<UnitByKeyLookupDictionary>(() => quantityInfos.SelectMany(quantityInfo => quantityInfo.UnitInfos).ToDictionary(x => x.UnitKey));
}

private UnitByKeyLookupDictionary GroupUnitsByKey()
{
return _quantities.SelectMany(quantityInfo => quantityInfo.UnitInfos).ToDictionary(x => x.UnitKey);
}

/// <summary>
/// Initializes a new instance of the <see cref="QuantityInfoLookup" /> class.
/// </summary>
/// <param name="quantityInfos">
/// A collection of <see cref="QuantityInfo" /> objects representing the quantities to be managed by this lookup.
/// </param>
/// <exception cref="ArgumentNullException">
/// Thrown when the <paramref name="quantityInfos" /> parameter is <c>null</c>.
/// </exception>
/// <remarks>
/// This constructor organizes the provided quantity information into internal lookup structures
/// for efficient access by name, unit type, and unit key.
/// </remarks>
public QuantityInfoLookup(IEnumerable<QuantityInfo> quantityInfos)
{
_quantities = quantityInfos.ToArray();
_quantitiesByName = new Lazy<QuantityByNameLookupDictionary>(GroupQuantitiesByName);
_quantitiesByUnitType = new Lazy<QuantityByTypeLookupDictionary>(GroupQuantitiesByUnitType);
_unitsByKey = new Lazy<UnitByKeyLookupDictionary>(GroupUnitsByKey);
}

/// <summary>
Expand All @@ -62,7 +84,7 @@ public QuantityInfoLookup(IReadOnlyCollection<QuantityInfo> quantityInfos)
/// <summary>
/// All quantity information objects, such as <see cref="Length.Info" /> and <see cref="Mass.Info" />.
/// </summary>
public IReadOnlyCollection<QuantityInfo> Infos => _quantitiesByName.Value.Values;
public IReadOnlyList<QuantityInfo> Infos => _quantities;

/// <summary>
/// Retrieves the <see cref="UnitInfo" /> for a specified <see cref="UnitKey" />.
Expand Down

0 comments on commit 6dc5f09

Please sign in to comment.