Skip to content

Commit d1cc5f8

Browse files
authored
🛡️Restrict number extension methods to INumber<T> (#1281)
Fixes #1269 Quantities implement `IConvertible.ToDouble()` by converting the `Value` property to `double`, and similar for other number types. Number extension methods expects a number argument, but take any argument type and call `Convert.ToDouble()` on it. This means you can run into subtle bugs: ```cs Length.FromCentimeters(100).Millimeters(); // Length of 100 mm Length.FromCentimeters(100).Millimeters; // Value of 1000 ``` The quantity implements conversions like this: ```cs double IConvertible.ToDouble(IFormatProvider? provider) { return Convert.ToDouble(_value); } ``` The extension method looks like this: ```cs public static Length Millimeters<T>(this T value) { return Length.FromMillimeters(Convert.ToDouble(value)); } ``` So `Convert.ToDouble()` happily converts `Length.FromCentimeters(100)` to `100`. ### Changes - Restrict number extension methods to `INumber<T>` for net7.0 and later
1 parent 9e826e3 commit d1cc5f8

File tree

123 files changed

+9528
-3016
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

123 files changed

+9528
-3016
lines changed

CodeGen/Generators/UnitsNetGen/NumberExtensionsGenerator.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ public string Generate()
2525
$@"
2626
using System;
2727
28+
#if NET7_0_OR_GREATER
29+
using System.Numerics;
30+
#endif
31+
2832
#nullable enable
2933
3034
namespace UnitsNet.NumberExtensions.NumberTo{_quantityName}
@@ -45,8 +49,12 @@ public static class NumberTo{_quantityName}Extensions
4549

4650
Writer.WLIfText(2, GetObsoleteAttributeOrNull(unit.ObsoleteText));
4751

48-
Writer.WL(2, $@"public static {_quantityName} {unit.PluralName}<T>(this T value) =>
49-
{_quantityName}.From{unit.PluralName}(Convert.ToDouble(value));
52+
Writer.WL(2, $@"public static {_quantityName} {unit.PluralName}<T>(this T value)
53+
where T : notnull
54+
#if NET7_0_OR_GREATER
55+
, INumber<T>
56+
#endif
57+
=> {_quantityName}.From{unit.PluralName}(Convert.ToDouble(value));
5058
");
5159
}
5260

UnitsNet.NumberExtensions.Tests/UnitsNet.NumberExtensions.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net6.0</TargetFramework>
4+
<TargetFramework>net7.0</TargetFramework>
55
<RootNamespace>UnitsNet.NumberExtensions.Tests</RootNamespace>
66
<LangVersion>latest</LangVersion>
77
<Nullable>enable</Nullable>

UnitsNet.NumberExtensions/GeneratedCode/NumberToAbsorbedDoseOfIonizingRadiationExtensions.g.cs

Lines changed: 100 additions & 32 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

UnitsNet.NumberExtensions/GeneratedCode/NumberToAccelerationExtensions.g.cs

Lines changed: 88 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)