Skip to content

[Breaking change]: Limiting the precision in numeric format strings from Int32.MaxValue to 999,999,999 #30352

@dakersnar

Description

@dakersnar

Description

The fix will likely be merged into .NET 7 RC1 with dotnet/runtime#72647.

in .NET 6, we updated the maximum precision for numeric format strings to be Int32.MaxValue, as documented here https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings and here https://docs.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/6.0/numeric-format-parsing-handles-higher-precision. Unfortunately, the implementation was buggy, and the easiest fix requires we pick a slightly smaller limit of 999,999,999. The original expansion to Int32.MaxValue was pretty arbitrary as far as I can tell, and 999,999,999 is more than big enough. This comment (dotnet/runtime#67891 (comment)) goes into a bit more detail on the logic of this choice.

Version

.NET 7 RC1

Previous behavior

The previous behavior intended to throw a FormatException for any precision larger than Int.MaxValue. It did not throw that exception for many of such inputs due to the mentioned bug. The intended behavior was:

double d = 123.0;

d.ToString("E" + int.MaxValue.ToString()); // doesn't throw

long intMaxPlus1 = (long)int.MaxValue + 1;
string intMaxPlus1String = intMaxPlus1.ToString();
Assert.Throws<FormatException>(() => d.ToString("E" + intMaxPlus1String)); // throws

New behavior

Now, we correctly throw a FormatException for any precision larger than 999,999,999.

double d = 123.0;
Assert.Throws<FormatException>(() => d.ToString("E" + int.MaxValue.ToString())); // throws

long intMaxPlus1 = (long)int.MaxValue + 1;
string intMaxPlus1String = intMaxPlus1.ToString();
Assert.Throws<FormatException>(() => d.ToString("E" + intMaxPlus1String)); // throws

d.ToString("E999999999"); // doesn't throw

d.ToString("E00000999999999"); // doesn't throw

Type of breaking change

  • Binary incompatible: Existing binaries may encounter a breaking change in behavior, such as failure to load/execute or different run-time behavior.
  • Source incompatible: Source code may encounter a breaking change in behavior when targeting the new runtime/component/SDK, such as compile errors or different run-time behavior.

Reason for change

Described above.

Recommended action

This change should not have any substantial effect, as I don't think many are using precisions this large. Simply updating the documentation should be sufficient.

Feature area

Core .NET libraries

Affected APIs

Should be the same APIs as the previous change https://docs.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/6.0/numeric-format-parsing-handles-higher-precision

Metadata

Metadata

Assignees

Labels

🏁 Release: .NET 7Work items for the .NET 7 releasebinary incompatibleExisting binaries may encounter a breaking change in behavior.breaking-changeIndicates a .NET Core breaking change

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions