Search code examples
c#.netformattingstring-formattingiformatprovider

String.Format vs int.ToString in regards to iCustomFormatter issue


I have the following two lines of code:

var BadResult = (100).ToString("B", new CustomFormatter ());
var GoodResult = String.Format("{0}", 100, new CustomFormatter ());

Whereas, BadResult obviously is bad, and GoodResult is good. My CustomFormatter class is declared like this: (also, with the one function I feel is relevant):

public class CustomFormatter 
               : IFormatProvider, ICustomFormatter
{
    public virtual Object GetFormat(Type formatType)
    {
        String formatTypeName = formatType.ToString();
        formatTypeName = formatTypeName;
        Object formatter = null;
        if (formatType == typeof(ICustomFormatter))
            formatter = this;
        return formatter;
    }
}

The issue itself, when I run the line of code with "good result", the GetFormat function is requestng an instance of CustomFormatter.

Whenever its called with Float.Tostring(), its expecting an instance of NumberFormatInfo.

I initially jumped to "my CustomFormatter should be deriving from NumberFormatInfo". Unfortunately, the class is sealed.

So: What do I need to do to be able to call Float.ToString() with a custom formatter?

Thanks!


Solution

  • I'm not sure you can use a custom formatter with Number.ToString. All the examples I've seen with custom formatters use String.Format (this on the MSDN for instance).

    I suggest you to try an extension method:

    public static class MyExt 
    {
        public static string ToFormattedString(this float This, string format, IFormatProvider provider)
        {
            return String.Format(provider,"{0}", new object[] {This});
        }
    }
    
    //now this works
    var NoLongerBadResult = (100F).ToFormattedString("B", new CustomFormatter ());
    

    EDIT ok, I think I got it. You need to change the current NumberFormatInfo and return it from GetFormat:

    public class CustomFormatter :  IFormatProvider, ICustomFormatter
    {
        public object GetFormat(Type formatType)
        {
            if (formatType == typeof(ICustomFormatter))
                return this;
            else if(formatType == typeof(NumberFormatInfo))
            {
                NumberFormatInfo nfi = (NumberFormatInfo)NumberFormatInfo.CurrentInfo.Clone(); // create a copy of the current NumberFormatInfo
                nfi.CurrencySymbol = "Foo"; // change the currency symbol to "Foo" (for instance)
                return nfi; // and return our clone
            }
            else
                return null;
        }
    
        public string Format(string fmt, object arg, IFormatProvider formatProvider)
        {
            return "test";
        }
    }
    

    now this works:

    var NowItWorks = (100).ToString("C", new CustomFormatter ());
    var GoodResult = String.Format(new CustomFormatter (),"{0}", 100);
    Console.WriteLine(NowItWorks); // Foo 100.00
    Console.WriteLine(GoodResult); // test