Skip to content

Commit 9090623

Browse files
authored
Update the ToString format of the BaseUnits/Dimensions (#1486)
- `BaseUnits`: no longer using the `AbbeviationsCache`, the new format is `L=Meter, M=Kilogram, T=Second` - `BaseDimensions`: the exponent moved inside the dimension-brackets: `[Length][Time^-1]` - `BaseDimensions`: minor performance improvements As mentioned in #1452, the main motivation here is the removal of the potential side effects of accessing/loading the unit abbreviations (e.g. during the `QuantityInfo` construction)
1 parent 1f90e8f commit 9090623

File tree

4 files changed

+80
-47
lines changed

4 files changed

+80
-47
lines changed

UnitsNet.Tests/BaseDimensionsTests.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public void IsBaseQuantity_ForAcceleration_ReturnsFalse()
7474
{
7575
Assert.False(Acceleration.BaseDimensions.IsBaseQuantity());
7676
}
77-
77+
7878
[Theory]
7979
[InlineData(2, 0, 0, 0, 0, 0, 0)]
8080
[InlineData(0, 2, 0, 0, 0, 0, 0)]
@@ -733,13 +733,13 @@ public void CheckBaseDimensionMultiplicationWithForceEqualsMassTimesAcceleration
733733
[Fact]
734734
public void CheckToStringUsingMolarEntropy()
735735
{
736-
Assert.Equal("[Length]^2[Mass][Time]^-2[Temperature]^-1[Amount]^-1", MolarEntropy.BaseDimensions.ToString());
736+
Assert.Equal("[Length^2][Mass][Time^-2][Temperature^-1][Amount^-1]", MolarEntropy.BaseDimensions.ToString());
737737
}
738738

739739
[Fact]
740740
public void CheckToStringUsingSpeed()
741741
{
742-
Assert.Equal("[Length][Time]^-1", Speed.BaseDimensions.ToString());
742+
Assert.Equal("[Length][Time^-1]", Speed.BaseDimensions.ToString());
743743
}
744744

745745
[Fact]
@@ -782,5 +782,6 @@ public void IsDimensionlessMethodImplementedCorrectly()
782782
// Example case
783783
Assert.True(Level.BaseDimensions.IsDimensionless());
784784
}
785+
785786
}
786787
}

UnitsNet.Tests/BaseUnitsTests.cs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -140,16 +140,21 @@ public void ToStringGivesExpectedResult()
140140
AmountOfSubstanceUnit.Mole,
141141
LuminousIntensityUnit.Candela);
142142

143-
UnitAbbreviationsCache cache = UnitsNetSetup.Default.UnitAbbreviations;
144-
var m = cache.GetDefaultAbbreviation(LengthUnit.Meter);
145-
var kg = cache.GetDefaultAbbreviation(MassUnit.Kilogram);
146-
var s = cache.GetDefaultAbbreviation(DurationUnit.Second);
147-
var A = cache.GetDefaultAbbreviation(ElectricCurrentUnit.Ampere);
148-
var K = cache.GetDefaultAbbreviation(TemperatureUnit.Kelvin);
149-
var mol = cache.GetDefaultAbbreviation(AmountOfSubstanceUnit.Mole);
150-
var cd = cache.GetDefaultAbbreviation(LuminousIntensityUnit.Candela);
151-
152-
Assert.Equal($"[Length]: {m}, [Mass]: {kg}, [Time]: {s}, [Current]: {A}, [Temperature]: {K}, [Amount]: {mol}, [LuminousIntensity]: {cd}", siBaseUnits.ToString());
143+
Assert.Equal("L=Meter, M=Kilogram, T=Second, I=Ampere, Θ=Kelvin, N=Mole, J=Candela", siBaseUnits.ToString());
144+
}
145+
146+
[Fact]
147+
public void ToString_WithFewerDimensions_ContainsOnlyTheSpecifiedDimensions()
148+
{
149+
var siBaseUnits = new BaseUnits(length:LengthUnit.Meter, mass:MassUnit.Gram, time:DurationUnit.Second, temperature:TemperatureUnit.DegreeCelsius);
150+
151+
Assert.Equal("L=Meter, M=Gram, T=Second, Θ=DegreeCelsius", siBaseUnits.ToString());
152+
}
153+
154+
[Fact]
155+
public void ToString_WithUndefinedUnits_ReturnsUndefined()
156+
{
157+
Assert.Equal("Undefined", BaseUnits.Undefined.ToString());
153158
}
154159

155160
[Fact]

UnitsNet/BaseDimensions.cs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
using System;
55
using System.Text;
6-
using System.Linq;
76

87
namespace UnitsNet
98
{
@@ -30,9 +29,13 @@ public BaseDimensions(int length, int mass, int time, int current, int temperatu
3029
/// <returns>True if the dimensions represent a base quantity, otherwise false.</returns>
3130
public bool IsBaseQuantity()
3231
{
33-
var dimensionsArray = new[] { Length, Mass, Time, Current, Temperature, Amount, LuminousIntensity };
34-
bool onlyOneEqualsOne = dimensionsArray.Select(dimension => dimension is 0 or 1 ? dimension : 2).Sum() == 1;
35-
return onlyOneEqualsOne;
32+
return (Length == 1 && Mass == 0 && Time == 0 && Current == 0 && Temperature == 0 && Amount == 0 && LuminousIntensity == 0) ||
33+
(Length == 0 && Mass == 1 && Time == 0 && Current == 0 && Temperature == 0 && Amount == 0 && LuminousIntensity == 0) ||
34+
(Length == 0 && Mass == 0 && Time == 1 && Current == 0 && Temperature == 0 && Amount == 0 && LuminousIntensity == 0) ||
35+
(Length == 0 && Mass == 0 && Time == 0 && Current == 1 && Temperature == 0 && Amount == 0 && LuminousIntensity == 0) ||
36+
(Length == 0 && Mass == 0 && Time == 0 && Current == 0 && Temperature == 1 && Amount == 0 && LuminousIntensity == 0) ||
37+
(Length == 0 && Mass == 0 && Time == 0 && Current == 0 && Temperature == 0 && Amount == 1 && LuminousIntensity == 0) ||
38+
(Length == 0 && Mass == 0 && Time == 0 && Current == 0 && Temperature == 0 && Amount == 0 && LuminousIntensity == 1);
3639
}
3740

3841
/// <summary>
@@ -71,7 +74,11 @@ public override bool Equals(object? obj)
7174
/// <inheritdoc />
7275
public override int GetHashCode()
7376
{
74-
return new {Length, Mass, Time, Current, Temperature, Amount, LuminousIntensity}.GetHashCode();
77+
#if NET
78+
return HashCode.Combine(Length, Mass, Time, Current, Temperature, Amount, LuminousIntensity);
79+
#else
80+
return new { Length, Mass, Time, Current, Temperature, Amount, LuminousIntensity }.GetHashCode();
81+
#endif
7582
}
7683

7784
/// <summary>
@@ -182,12 +189,16 @@ public override string ToString()
182189

183190
private static void AppendDimensionString(StringBuilder sb, string name, int value)
184191
{
185-
if (0 != value)
192+
switch (value)
186193
{
187-
sb.AppendFormat("[{0}]", name);
188-
189-
if (1 != value)
190-
sb.AppendFormat("^{0}", value);
194+
case 0:
195+
return;
196+
case 1:
197+
sb.AppendFormat("[{0}]", name);
198+
break;
199+
default:
200+
sb.AppendFormat("[{0}^{1}]", name, value);
201+
break;
191202
}
192203
}
193204

UnitsNet/BaseUnits.cs

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Copyright 2013 Andreas Gullberg Larsen ([email protected]). Maintained at https://github.com/angularsen/UnitsNet.
33

44
using System;
5-
using System.Text;
5+
using System.Collections.Generic;
66
using UnitsNet.Units;
77

88
namespace UnitsNet
@@ -103,11 +103,11 @@ public bool IsSubsetOf(BaseUnits other)
103103
/// <inheritdoc />
104104
public override int GetHashCode()
105105
{
106-
#if NET
106+
#if NET
107107
return HashCode.Combine(Length, Mass, Time, Current, Temperature, Amount, LuminousIntensity);
108-
#else
108+
#else
109109
return new {Length, Mass, Time, Current, Temperature, Amount, LuminousIntensity}.GetHashCode();
110-
#endif
110+
#endif
111111
}
112112

113113
/// <summary>
@@ -133,31 +133,47 @@ public override int GetHashCode()
133133
{
134134
return !(left == right);
135135
}
136-
136+
137137
/// <inheritdoc />
138138
public override string ToString()
139139
{
140-
if(!Equals(Undefined))
140+
if (Equals(Undefined))
141141
{
142-
var sb = new StringBuilder();
143-
144-
string GetDefaultAbbreviation<TUnitType>(TUnitType? unitOrNull) where TUnitType : struct, Enum => unitOrNull is { } unit
145-
? UnitsNetSetup.Default.UnitAbbreviations.GetDefaultAbbreviation(unit)
146-
: "N/A";
142+
return "Undefined";
143+
}
147144

148-
sb.AppendFormat("[Length]: {0}, ", GetDefaultAbbreviation(Length));
149-
sb.AppendFormat("[Mass]: {0}, ", GetDefaultAbbreviation(Mass));
150-
sb.AppendFormat("[Time]: {0}, ", GetDefaultAbbreviation(Time));
151-
sb.AppendFormat("[Current]: {0}, ", GetDefaultAbbreviation(Current));
152-
sb.AppendFormat("[Temperature]: {0}, ", GetDefaultAbbreviation(Temperature));
153-
sb.AppendFormat("[Amount]: {0}, ", GetDefaultAbbreviation(Amount));
154-
sb.AppendFormat("[LuminousIntensity]: {0}", GetDefaultAbbreviation(LuminousIntensity));
145+
return string.Join(", ", GetUnitsDefined());
155146

156-
return sb.ToString();
157-
}
158-
else
147+
IEnumerable<string> GetUnitsDefined()
159148
{
160-
return "Undefined";
149+
if (Length is not null)
150+
{
151+
yield return $"L={Length}";
152+
}
153+
if (Mass is not null)
154+
{
155+
yield return $"M={Mass}";
156+
}
157+
if (Time is not null)
158+
{
159+
yield return $"T={Time}";
160+
}
161+
if (Current is not null)
162+
{
163+
yield return $"I={Current}";
164+
}
165+
if (Temperature is not null)
166+
{
167+
yield return $"Θ={Temperature}";
168+
}
169+
if (Amount is not null)
170+
{
171+
yield return $"N={Amount}";
172+
}
173+
if (LuminousIntensity is not null)
174+
{
175+
yield return $"J={LuminousIntensity}";
176+
}
161177
}
162178
}
163179

@@ -200,8 +216,8 @@ string GetDefaultAbbreviation<TUnitType>(TUnitType? unitOrNull) where TUnitType
200216
/// Gets a value indicating whether all base units are defined.
201217
/// </summary>
202218
/// <remarks>
203-
/// This property returns <c>true</c> if all seven base units
204-
/// (Length, Mass, Time, Current, Temperature, Amount, and LuminousIntensity)
219+
/// This property returns <c>true</c> if all seven base units
220+
/// (Length, Mass, Time, Current, Temperature, Amount, and LuminousIntensity)
205221
/// are non-null; otherwise, it returns <c>false</c>.
206222
/// </remarks>
207223
public bool IsFullyDefined => Length is not null &&

0 commit comments

Comments
 (0)