Repository navigation
Document unit-test / theory-data impact of .NET 11 double→decimal conversion #56487
Description
Type of issue
- Content issue (typos, broken links, missing/outdated content)
- Product issue (bug in docs tooling/platform)
Location
- https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/11/decimal-biginteger-floating-point-conversions
- Source:
docs/core/compatibility/core-libraries/11/decimal-biginteger-floating-point-conversions.md - Also referenced from
docs/core/whats-new/dotnet-11/libraries.md
Description
The breaking-change page correctly documents that float/double → decimal is now correctly rounded (exact binary value), and recommends decimal literals (1.23m) instead of casting double literals.
What is easy to miss in migration: unit-test theory / inline data often injects floating literals as double, then binds or casts them to decimal parameters. That path was “quietly OK” on .NET 10 (15-digit-style conversion) and fails equality / validation on .NET 11 even when production code already uses decimal end-to-end.
xUnit
// Compiles: 0.1 is a double attribute argument
[Theory]
[InlineData(0.1)]
public void Rate(decimal rate)
{
// Under .NET 10: rate often equals 0.1m
// Under .NET 11: rate == 0.1000000000000000055511151231m → assert fails
Assert.Equal(0.1m, rate);
}
// Does NOT compile: decimal is not a valid C# attribute argument type
// [InlineData(0.1m)]Workaround that keeps real decimals: MemberData / ClassData / TheoryData<decimal> with 0.1m values (not attribute args).
NUnit
// Non-m literals become double, then convert to decimal param
[TestCase(0.1)]
public void Rate(decimal rate) { ... }
// Prefer:
[TestCase("0.1")]
public void Rate(decimal rate) { ... } // parsed as decimalWhy document this on the BC page
- The failure mode is often tests only, so teams can think production is broken when CI is.
- It is not obvious that
InlineData(0.1)+decimalis a double conversion (C# forbids0.1min attributes). - Same BC already says “don’t assume a binary FP literal and a decimal literal with the same source text represent the same value” — a short “Impact on unit tests” subsection with xUnit/NUnit examples would catch a large class of migration failures.
Suggested addition (sketch)
Under Recommended action, add something like:
Unit tests (xUnit / NUnit / similar)
Theory/case attributes cannot take decimal constants in C#. Non-integer numeric attribute args are double/float. Binding those to decimal parameters uses the same conversion as (decimal)double and therefore changes under this BC. Prefer:
- xUnit:
TheoryData/MemberDatawithdecimalvalues (0.1m), or string data +decimal.Parse - NUnit:
[TestCase("0.1")]intodecimal, or explicit0.1monly outside attributes
Page URL
Related
- Runtime BC is intentional; this is a docs request only (no ask to revert conversion).
- xUnit docs request: Docs: prefer MemberData/TheoryData for decimal theories (breaks harder on .NET 11) xunit/xunit#3658
- xUnit attribute limitation is language-level (
decimalnot allowed in attribute arguments).
Activity