Search code examples
c#formatting

Calling ToString with own IFormatProvider doesn't work


This is about IFormattable and IFormatProvider. For sure one can achieve a reversed string representation of value 123 otherwise...

Every C# base data type implements the IFormattable interface. So such a data type provides the method

public string ToString(string format, IFormatProvider formatProvider);

which allows according to the Microsoft documentation both:

  1. You can also define your own format strings to support formatting of your application-defined types.

  2. In addition, you can define your own custom format providers to supply culture-specific, profession-specific, or industry-specific information used in formatting.

From that is should be possible to write:

// Shall produce "321"
string s = 123.ToString("Z", ReverseFormatProvider);

where "Z" is my own format string and ReverseFormatProvider is my own (custom) format providers.

I followed the ICustomFormatter interface example https://learn.microsoft.com/en-us/dotnet/api/system.icustomformatter?view=net-8.0.

But it uses only String.Format and not ToString directly as Microsoft documentation says for ToString:

You can call the method directly. It is also called automatically by the Convert.ToString(Object) and Convert.ToString(Object, IFormatProvider) methods, and by methods that use the composite formatting feature in the .NET Framework, such as String.Format(String, Object[]), ...

In my ReverseFormatProvider GetFormat always receives NumberFormatInfo as formatType.

And as a consequence ToString("Z", new ReverseFormatProvider()) throws a System.FormatException (unknown format string).

How do I manage to "attach" custom formatting to base data types by means of IFormatProvider?


Solution

  • Based on what I see in the docs and Int32.ToString implementation it is impossible to define your own format string/format specifier.

    From the How to: Define and Use Custom Numeric Format Providers doc:

    .NET gives you extensive control over the string representation of numeric values. It supports the following features for customizing the format of numeric values:

    • Standard numeric format strings, which provide a predefined set of formats for converting numbers to their string representation. You can use them with any numeric formatting method, such as Decimal.ToString(String), that has a format parameter. For details, see Standard Numeric Format Strings.
    • Custom numeric format strings, which provide a set of symbols that can be combined to define custom numeric format specifiers. They can also be used with any numeric formatting method, such as Decimal.ToString(String), that has a format parameter. For details, see Custom Numeric Format Strings.
    • Custom CultureInfo or NumberFormatInfo objects, which define the symbols and format patterns used in displaying the string representations of numeric values. You can use them with any numeric formatting method, such as ToString, that has a provider parameter. Typically, the provider parameter is used to specify culture-specific formatting.

    Hence the IFormatProvider (CultureInfo/NumberFormatInfo) is usually responsible for culture-specific information (like delimiters and so on) and will be used if you use one of the predefined formats or build a custom one from predefined set of custom format specifiers.