Skip to content

Write values in the invariant culture when they are parsed with it [patch] - #102

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/97-invariant-write-culture
Sep 27, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/97-invariant-write-culture

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #97

What changed

Since #96, a conversion method that takes an IFormatProvider is called with CultureInfo.InvariantCulture. Write and WriteAsPropertyName still formatted with plain ToString(), which uses the current culture. Under a culture with , as the decimal separator, Complex(1.5, 2.5) was written as <1,5; 2,5> and read back as <15; 25>, and no error was raised.

  • Added ReadsWithInvariantCulture, which is true when the selected conversion method has an IFormatProvider parameter (the same condition under which BuildArguments passes the invariant culture).
  • Added FormatValue. When that flag is set and the value is IFormattable, it writes ToString(null, CultureInfo.InvariantCulture). Otherwise it keeps ToString().
  • Write and WriteAsPropertyName both use FormatValue.

This follows the issue's "at minimum" option on purpose. A type read through a single-string Parse parses with the current culture, so its ToString() is left alone. Changing it would break that type's round trip instead.

Tests

New CultureRoundTripTests, run under a culture with , as the decimal separator:

  • Complex round-trips unchanged
  • a Parse(string, IFormatProvider) type round-trips as a property and as a dictionary key
  • control case: a type with a current-culture Parse(string) keeps writing "1,5" and round-trips

The test project runs with System.Globalization.Invariant: true (set by ktsu.Sdk), so de-DE can't be created there. The tests use a writable clone of the invariant culture with de-DE's decimal and group separators instead. That exercises the same formatting path on every CI runner and doesn't change the globalization mode for the whole test project.

Without the fix, the three round-trip cases fail and 102 other tests pass. With it, all 105 tests pass. The library builds cleanly for all its target frameworks.

This PR is independent of #100 and #101. All three start from main.

🤖 Generated with Claude Code

https://claude.ai/code/session_01B9RFdjRB3ff72GWre48NPs


Generated by Claude Code

…atch]

A conversion method that takes an IFormatProvider is called with the
invariant culture, but Write and WriteAsPropertyName formatted with plain
ToString(), which uses the current culture. Under a ',' decimal culture,
Complex(1.5, 2.5) came back as <15; 25> with no error. Such values are now
written through IFormattable.ToString(null, InvariantCulture); types
parsed with a single-string method keep their own ToString().

Fixes #97

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B9RFdjRB3ff72GWre48NPs
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants