Skip to content

Commit 9158c72

Browse files
committed
UnitSystem: Throw UnitNotFoundException when no unit matches parsed abbreviation
Breaking change, but it was a silly default behavior to default to Undefined if parsing failed. Now throws exception instead. TryParse() serves the purpose of non-exception parsing. Update test cases
1 parent 2bc2d67 commit 9158c72

File tree

3 files changed

+54
-45
lines changed

3 files changed

+54
-45
lines changed

UnitsNet.Tests/CustomCode/ParseTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public void ParseLengthUnitUsEnglish(string s, LengthUnit expected)
148148
}
149149

150150
[Theory]
151-
[InlineData("kg", "UnitsNet.UnitsNetException")]
151+
[InlineData("kg", "UnitsNet.UnitNotFoundException")]
152152
[InlineData(null, "System.ArgumentNullException")]
153153
public void ParseLengthUnitUsEnglish_ThrowsExceptionOnInvalidString(string s, string expected)
154154
{

UnitsNet.Tests/UnitSystemTests.cs

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,6 @@ private enum CustomUnit
6969
// ReSharper restore UnusedMember.Local
7070
}
7171

72-
#if !WINDOWS_UWP
73-
private UnitSystem GetCachedUnitSystem()
74-
{
75-
Culture culture = GetCulture("en-US");
76-
UnitSystem unitSystem = UnitSystem.GetCached(culture);
77-
return unitSystem;
78-
}
79-
#endif
80-
8172
private static IEnumerable<object> GetUnitTypesWithMissingAbbreviations<TUnitType>(string cultureName,
8273
IEnumerable<TUnitType> unitValues)
8374
where TUnitType : /*Enum constraint hack*/ struct, IComparable, IFormattable
@@ -180,15 +171,21 @@ public void DecimalPointDigitGroupingCultureFormatting(string culture)
180171

181172
#if !WINDOWS_UWP
182173
[Theory]
183-
[InlineData("m^2", AreaUnit.SquareMeter)]
184-
[InlineData("cm^2", AreaUnit.Undefined)]
185-
public void Parse_ReturnsUnitMappedByCustomAbbreviationOrUndefined(string unitAbbreviationToParse, AreaUnit expected)
174+
[InlineData("m^^2", AreaUnit.SquareMeter)]
175+
[InlineData("cm^^2", AreaUnit.SquareCentimeter)]
176+
public void Parse_ReturnsUnitMappedByCustomAbbreviation(string customAbbreviation, AreaUnit expected)
186177
{
187-
UnitSystem unitSystem = GetCachedUnitSystem();
188-
unitSystem.MapUnitToAbbreviation(AreaUnit.SquareMeter, "m^2");
189-
var actual = unitSystem.Parse<AreaUnit>(unitAbbreviationToParse);
178+
UnitSystem unitSystem = UnitSystem.Default;
179+
unitSystem.MapUnitToAbbreviation(expected, customAbbreviation);
180+
var actual = unitSystem.Parse<AreaUnit>(customAbbreviation);
190181
Assert.Equal(expected, actual);
191182
}
183+
184+
[Fact]
185+
public void Parse_UnknownAbbreviationThrowsUnitNotFoundException()
186+
{
187+
Assert.Throws<UnitNotFoundException>(() => UnitSystem.Default.Parse<AreaUnit>("nonexistingunit"));
188+
}
192189
#endif
193190

194191
[Theory]
@@ -296,31 +293,31 @@ public void ShouldUseCorrectMicroSign()
296293
Assert.Equal(VolumeUnit.CubicMicrometer, Volume.ParseUnit("\u00b5m³"));
297294

298295
// "\u03bc" = Lower case greek letter 'Mu'
299-
Assert.Throws<UnitsNetException>(() => Acceleration.ParseUnit("\u03bcm/s²"));
300-
Assert.Throws<UnitsNetException>(() => AmplitudeRatio.ParseUnit("dB\u03bcV"));
301-
Assert.Throws<UnitsNetException>(() => Angle.ParseUnit("\u03bc°"));
302-
Assert.Throws<UnitsNetException>(() => Angle.ParseUnit("\u03bcrad"));
303-
Assert.Throws<UnitsNetException>(() => Area.ParseUnit("\u03bcm²"));
304-
Assert.Throws<UnitsNetException>(() => Duration.ParseUnit("\u03bcs"));
305-
Assert.Throws<UnitsNetException>(() => ElectricCurrent.ParseUnit("\u03bcA"));
306-
Assert.Throws<UnitsNetException>(() => ElectricPotential.ParseUnit("\u03bcV"));
307-
Assert.Throws<UnitsNetException>(() => Flow.ParseUnit("\u03bcLPM"));
308-
Assert.Throws<UnitsNetException>(() => ForceChangeRate.ParseUnit("\u03bcN/s"));
309-
Assert.Throws<UnitsNetException>(() => ForcePerLength.ParseUnit("\u03bcN/m"));
310-
Assert.Throws<UnitsNetException>(() => KinematicViscosity.ParseUnit("\u03bcSt"));
311-
Assert.Throws<UnitsNetException>(() => Length.ParseUnit("\u03bcin"));
312-
Assert.Throws<UnitsNetException>(() => Length.ParseUnit("\u03bcm"));
313-
Assert.Throws<UnitsNetException>(() => MassFlow.ParseUnit("\u03bcg/S"));
314-
Assert.Throws<UnitsNetException>(() => Mass.ParseUnit("\u03bcg"));
315-
Assert.Throws<UnitsNetException>(() => Power.ParseUnit("\u03bcW"));
316-
Assert.Throws<UnitsNetException>(() => Pressure.ParseUnit("\u03bcPa"));
317-
Assert.Throws<UnitsNetException>(() => RotationalSpeed.ParseUnit("\u03bc°/s"));
318-
Assert.Throws<UnitsNetException>(() => RotationalSpeed.ParseUnit("\u03bcrad/s"));
319-
Assert.Throws<UnitsNetException>(() => Speed.ParseUnit("\u03bcm/min"));
320-
Assert.Throws<UnitsNetException>(() => Speed.ParseUnit("\u03bcm/s"));
321-
Assert.Throws<UnitsNetException>(() => TemperatureChangeRate.ParseUnit("\u03bc°C/s"));
322-
Assert.Throws<UnitsNetException>(() => Volume.ParseUnit("\u03bcl"));
323-
Assert.Throws<UnitsNetException>(() => Volume.ParseUnit("\u03bcm³"));
296+
Assert.Throws<UnitNotFoundException>(() => Acceleration.ParseUnit("\u03bcm/s²"));
297+
Assert.Throws<UnitNotFoundException>(() => AmplitudeRatio.ParseUnit("dB\u03bcV"));
298+
Assert.Throws<UnitNotFoundException>(() => Angle.ParseUnit("\u03bc°"));
299+
Assert.Throws<UnitNotFoundException>(() => Angle.ParseUnit("\u03bcrad"));
300+
Assert.Throws<UnitNotFoundException>(() => Area.ParseUnit("\u03bcm²"));
301+
Assert.Throws<UnitNotFoundException>(() => Duration.ParseUnit("\u03bcs"));
302+
Assert.Throws<UnitNotFoundException>(() => ElectricCurrent.ParseUnit("\u03bcA"));
303+
Assert.Throws<UnitNotFoundException>(() => ElectricPotential.ParseUnit("\u03bcV"));
304+
Assert.Throws<UnitNotFoundException>(() => Flow.ParseUnit("\u03bcLPM"));
305+
Assert.Throws<UnitNotFoundException>(() => ForceChangeRate.ParseUnit("\u03bcN/s"));
306+
Assert.Throws<UnitNotFoundException>(() => ForcePerLength.ParseUnit("\u03bcN/m"));
307+
Assert.Throws<UnitNotFoundException>(() => KinematicViscosity.ParseUnit("\u03bcSt"));
308+
Assert.Throws<UnitNotFoundException>(() => Length.ParseUnit("\u03bcin"));
309+
Assert.Throws<UnitNotFoundException>(() => Length.ParseUnit("\u03bcm"));
310+
Assert.Throws<UnitNotFoundException>(() => MassFlow.ParseUnit("\u03bcg/S"));
311+
Assert.Throws<UnitNotFoundException>(() => Mass.ParseUnit("\u03bcg"));
312+
Assert.Throws<UnitNotFoundException>(() => Power.ParseUnit("\u03bcW"));
313+
Assert.Throws<UnitNotFoundException>(() => Pressure.ParseUnit("\u03bcPa"));
314+
Assert.Throws<UnitNotFoundException>(() => RotationalSpeed.ParseUnit("\u03bc°/s"));
315+
Assert.Throws<UnitNotFoundException>(() => RotationalSpeed.ParseUnit("\u03bcrad/s"));
316+
Assert.Throws<UnitNotFoundException>(() => Speed.ParseUnit("\u03bcm/min"));
317+
Assert.Throws<UnitNotFoundException>(() => Speed.ParseUnit("\u03bcm/s"));
318+
Assert.Throws<UnitNotFoundException>(() => TemperatureChangeRate.ParseUnit("\u03bc°C/s"));
319+
Assert.Throws<UnitNotFoundException>(() => Volume.ParseUnit("\u03bcl"));
320+
Assert.Throws<UnitNotFoundException>(() => Volume.ParseUnit("\u03bcm³"));
324321
}
325322

326323
[Theory]
@@ -490,7 +487,7 @@ public void NotANumberFormatting()
490487
[Fact]
491488
public void Parse_AmbiguousUnitsThrowsException()
492489
{
493-
UnitSystem unitSystem = GetCachedUnitSystem();
490+
UnitSystem unitSystem = UnitSystem.Default;
494491

495492
// Act 1
496493
Assert.Throws<AmbiguousUnitParseException>(() => unitSystem.Parse<VolumeUnit>("tsp"));

UnitsNet/CustomCode/UnitSystem.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
using JetBrains.Annotations;
2727
using UnitsNet.I18n;
2828
using UnitsNet.InternalHelpers;
29+
using UnitsNet.Units;
2930

3031
// ReSharper disable once CheckNamespace
3132
namespace UnitsNet
@@ -235,13 +236,24 @@ TUnitType Parse<TUnitType>(string unitAbbreviation)
235236
return (TUnitType) Parse(unitAbbreviation, typeof(TUnitType));
236237
}
237238

239+
/// <summary>
240+
/// Parse a unit abbreviation, such as "kg" or "m", to the unit enum value of the enum type
241+
/// <paramref name="unitType" />.
242+
/// </summary>
243+
/// <param name="unitAbbreviation">
244+
/// Unit abbreviation, such as "kg" or "m" for <see cref="MassUnit.Kilogram" /> and
245+
/// <see cref="LengthUnit.Meter" /> respectively.
246+
/// </param>
247+
/// <param name="unitType">Unit enum type, such as <see cref="MassUnit" /> and <see cref="LengthUnit" />.</param>
248+
/// <returns>Unit enum value, such as <see cref="MassUnit.Kilogram" />.</returns>
249+
/// <exception cref="UnitNotFoundException">No units match the abbreviation.</exception>
250+
/// <exception cref="AmbiguousUnitParseException">More than one unit matches the abbrevation.</exception>
238251
[PublicAPI]
239252
public object Parse(string unitAbbreviation, Type unitType)
240253
{
241254
AbbreviationMap abbrevToUnitValue;
242255
if (!_unitTypeToAbbrevToUnitValue.TryGetValue(unitType, out abbrevToUnitValue))
243-
throw new NotImplementedException(
244-
$"No abbreviations defined for unit type [{unitType}] for culture [{Culture}].");
256+
throw new UnitNotFoundException($"No abbreviations defined for unit type [{unitType}] for culture [{Culture}].");
245257

246258
List<int> unitIntValues;
247259
List<object> unitValues = abbrevToUnitValue.TryGetValue(unitAbbreviation, out unitIntValues)
@@ -253,7 +265,7 @@ public object Parse(string unitAbbreviation, Type unitType)
253265
case 1:
254266
return unitValues[0];
255267
case 0:
256-
return 0;
268+
throw new UnitNotFoundException($"Unit not found with abbreviation [{unitAbbreviation}] for unit type [{unitType}].");
257269
default:
258270
string unitsCsv = string.Join(", ", unitValues.Select(x => x.ToString()).ToArray());
259271
throw new AmbiguousUnitParseException(

0 commit comments

Comments
 (0)