Skip to content

Commit fd6e0e1

Browse files
Updated projects to target .NET 11 (#1014)
* Updated projects in the solution to target .NET 11 - Added .NET 11 target to the MiniExcel source main projects and test projects - Replaced the .NET 9 target with the .NET 11 target in the benchmark project - Added .NET 11 as one of the dotnet versions to build and test for in github actions * Addressed a breaking change regarding double to decimal conversion introduced in .NET 11 In .NET 11 conversion APIs such as `new Decimal(double value)` or `Convert.ToDecimal(double value)` among others have been changed to approximate the resulting value more accurately. Unfortunately this is a significant breaking change for us as we relied upon this truncation to discard unwanted decimal digits when mapping doubles (our default numeric type) to decimals. Hence a workaround was added to ensure backwards compatibility was mantained. * Updating codeql and benchmark workflows
1 parent 2ecd46f commit fd6e0e1

11 files changed

Lines changed: 72 additions & 15 deletions

File tree

‎.github/workflows/benchmark.yml‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ jobs:
1717
- name: Setup .NET
1818
uses: actions/setup-dotnet@v4
1919
with:
20-
dotnet-version: 10.0.x
20+
dotnet-version: 11.0.x
2121
- name: Restore dependencies
2222
run: dotnet restore
2323
working-directory: ./benchmarks/MiniExcel.Benchmarks
2424
- name: Build
2525
run: dotnet build --no-restore
2626
working-directory: ./benchmarks/MiniExcel.Benchmarks
2727
- name: Benchmark
28-
run: dotnet run -c Release -f net10.0
28+
run: dotnet run -c Release -f net11.0
2929
working-directory: ./benchmarks/MiniExcel.Benchmarks
3030
env:
3131
BenchmarkMode: Automatic
@@ -47,15 +47,15 @@ jobs:
4747
- name: Setup .NET
4848
uses: actions/setup-dotnet@v4
4949
with:
50-
dotnet-version: 10.0.x
50+
dotnet-version: 11.0.x
5151
- name: Restore dependencies
5252
run: dotnet restore
5353
working-directory: ./benchmarks/MiniExcel.Benchmarks
5454
- name: Build
5555
run: dotnet build --no-restore
5656
working-directory: ./benchmarks/MiniExcel.Benchmarks
5757
- name: Benchmark
58-
run: dotnet run -c Release -f net10.0
58+
run: dotnet run -c Release -f net11.0
5959
working-directory: ./benchmarks/MiniExcel.Benchmarks
6060
env:
6161
BenchmarkMode: Automatic
@@ -77,15 +77,15 @@ jobs:
7777
- name: Setup .NET
7878
uses: actions/setup-dotnet@v4
7979
with:
80-
dotnet-version: 10.0.x
80+
dotnet-version: 11.0.x
8181
- name: Restore dependencies
8282
run: dotnet restore
8383
working-directory: ./benchmarks/MiniExcel.Benchmarks
8484
- name: Build
8585
run: dotnet build --no-restore
8686
working-directory: ./benchmarks/MiniExcel.Benchmarks
8787
- name: Benchmark
88-
run: dotnet run -c Release -f net10.0
88+
run: dotnet run -c Release -f net11.0
8989
working-directory: ./benchmarks/MiniExcel.Benchmarks
9090
env:
9191
BenchmarkMode: Automatic

‎.github/workflows/codeql-analysis.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343
- name: Setup .NET
4444
uses: actions/setup-dotnet@v4
4545
with:
46-
dotnet-version: 10.0.x
46+
dotnet-version: 11.0.x
4747

4848
- name: Restore dependencies
4949
run: dotnet restore

‎.github/workflows/dotnet.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ jobs:
1919
8.0.x
2020
9.0.x
2121
10.0.x
22+
11.0.x
2223
- name: Restore dependencies
2324
run: dotnet restore
2425
env:

‎benchmarks/MiniExcel.Benchmarks/MiniExcel.Benchmarks.csproj‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFrameworks>net9.0;net10.0</TargetFrameworks>
5+
<TargetFrameworks>net10.0;net11.0</TargetFrameworks>
66
<Nullable>enable</Nullable>
77
<ImplicitUsings>enable</ImplicitUsings>
88
<LangVersion>latest</LangVersion>

‎src/Directory.Build.props‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<Project>
22

33
<PropertyGroup>
4-
<TargetFrameworks>netstandard2.0;net8.0;net9.0;net10.0</TargetFrameworks>
4+
<TargetFrameworks>netstandard2.0;net8.0;net9.0;net10.0;net11.0</TargetFrameworks>
55
<Version>2.0.0-preview.4</Version>
66
<Nullable>enable</Nullable>
77
<ImplicitUsings>enable</ImplicitUsings>
8-
<LangVersion>14</LangVersion>
8+
<LangVersion>preview</LangVersion>
99
</PropertyGroup>
1010

1111
<PropertyGroup>

‎src/MiniExcel.Core/Helpers/Polyfills.cs‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,26 @@ public static ValueTask<ZipArchive> CreateAsync(Stream stream, ZipArchiveMode mo
155155
}
156156
}
157157
#endif
158+
159+
#if NET11_0_OR_GREATER
160+
extension(Convert)
161+
{
162+
/// <summary>Converts the specified double value to decimal using the same approximation applied by versions of .NET no greater than 10.</summary>
163+
/// <remarks>
164+
/// In .NET 11 conversion APIs such as <see cref="Decimal(double)" /> and <see cref="Convert.ToDecimal(double)" /> among others
165+
/// have been changed to approximate the resulting value more accurately. Unfortunately this is a significant breaking change for us
166+
/// as we relied upon this truncation to discard unwanted decimal digits when mapping doubles (our default numeric type) to decimals.
167+
/// This method is therefore a workaround to ensure backwards compatibility with previous versions of the library.
168+
/// </remarks>
169+
[EditorBrowsable(EditorBrowsableState.Advanced)]
170+
public static decimal ToDecimalWithLegacyApproximation(double value)
171+
{
172+
Span<char> text = stackalloc char[32];
173+
value.TryFormat(text, out var length, "G15", CultureInfo.InvariantCulture);
174+
return decimal.Parse(text[..length], NumberStyles.Float, CultureInfo.InvariantCulture);
175+
}
176+
}
177+
#endif
158178
}
159179

160180
#if NETSTANDARD2_0

‎src/MiniExcel.Core/MiniExcelDataReaderBase.cs‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,12 @@ public virtual byte GetByte(int i) => GetValue(i) is { } value
136136

137137
public virtual decimal GetDecimal(int i) => GetValue(i) switch
138138
{
139-
decimal d => d,
139+
decimal dec => dec,
140+
#if NET11_0_OR_GREATER
141+
double f64 => Convert.ToDecimalWithLegacyApproximation(f64),
142+
#else
143+
double f64 => Convert.ToDecimal(f64, CultureInfo.InvariantCulture),
144+
#endif
140145
null => throw new InvalidOperationException("The value is null"),
141146
var value => Convert.ToDecimal(value, MiniExcelConfiguration.Culture)
142147
};

‎src/MiniExcel.Core/Reflection/MiniExcelMapper.cs‎

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,11 @@ public static partial class MiniExcelMapper
214214

215215
else if (map.ExcludeNullableType == typeof(double))
216216
{
217-
if (double.TryParse(Convert.ToString(itemValue, config.Culture), NumberStyles.Any, config.Culture, out var doubleValue))
217+
if (itemValue is double f64)
218+
{
219+
newValue = f64;
220+
}
221+
else if (double.TryParse(Convert.ToString(itemValue, config.Culture), NumberStyles.Any, config.Culture, out var doubleValue))
218222
{
219223
newValue = doubleValue;
220224
}
@@ -227,6 +231,33 @@ public static partial class MiniExcelMapper
227231
}
228232
}
229233

234+
else if (map.ExcludeNullableType == typeof(decimal))
235+
{
236+
if (itemValue is decimal dec)
237+
{
238+
newValue = dec;
239+
}
240+
else if (itemValue is double f64)
241+
{
242+
#if NET11_0_OR_GREATER
243+
newValue = Convert.ToDecimalWithLegacyApproximation(f64);
244+
#else
245+
newValue = Convert.ToDecimal(f64, CultureInfo.InvariantCulture);
246+
#endif
247+
}
248+
else if (decimal.TryParse(Convert.ToString(itemValue, config.Culture), NumberStyles.Any, config.Culture, out var decimalValue))
249+
{
250+
newValue = decimalValue;
251+
}
252+
else
253+
{
254+
var invariantString = Convert.ToString(itemValue, CultureInfo.InvariantCulture);
255+
newValue = decimal.TryParse(invariantString, NumberStyles.Any, CultureInfo.InvariantCulture, out var value)
256+
? value
257+
: throw new InvalidCastException();
258+
}
259+
}
260+
230261
else if (map.ExcludeNullableType == typeof(bool))
231262
{
232263
var vs = itemValue?.ToString();

‎tests/MiniExcel.Csv.Tests/MiniExcel.Csv.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-
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
4+
<TargetFrameworks>net8.0;net9.0;net10.0;net11.0</TargetFrameworks>
55
<ImplicitUsings>enable</ImplicitUsings>
66
<Nullable>enable</Nullable>
77
<NoWarn>$(NoWarn);IDE0017;IDE0034;IDE0037;IDE0039;IDE0042;IDE0044;IDE0051;IDE0052;IDE0059;IDE0060;IDE0063;IDE1006;xUnit1004;CA1806;CA1816;CA1822;CA1825;CA1849;CA2000;CA2007;CA2208</NoWarn>

‎tests/MiniExcel.OpenXml.Tests/MiniExcel.OpenXml.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-
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
4+
<TargetFrameworks>net8.0;net9.0;net10.0;net11.0</TargetFrameworks>
55
<ImplicitUsings>enable</ImplicitUsings>
66
<Nullable>enable</Nullable>
77
<NoWarn>$(NoWarn);IDE0017;IDE0034;IDE0037;IDE0039;IDE0042;IDE0044;IDE0051;IDE0052;IDE0059;IDE0060;IDE0063;IDE1006;xUnit1004;CA1806;CA1816;CA1822;CA1825;CA1849;CA2000;CA2007;CA2208</NoWarn>

0 commit comments

Comments
 (0)