Skip to content

Document unit-test / theory-data impact of .NET 11 double→decimal conversion #56487

Open

Description

@florianwakam

Type of issue

  • Content issue (typos, broken links, missing/outdated content)
  • Product issue (bug in docs tooling/platform)

Location

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 decimal

Why 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) + decimal is a double conversion (C# forbids 0.1m in 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 / MemberData with decimal values (0.1m), or string data + decimal.Parse
  • NUnit: [TestCase("0.1")] into decimal, or explicit 0.1m only outside attributes

Page URL

https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/11/decimal-biginteger-floating-point-conversions

Related

Related Issues

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions