Custom IFormatProvider for doubles

The following example shows how to write a custom IFormatProvider which you can use in String.Format(IFormatProvider, ...).

public class DoubleFormatter : IFormatProvider, ICustomFormatter

{

    // always use dot separator for doubles

    private CultureInfo enUsCulture =

        CultureInfo.GetCultureInfo("en-US");

 

    public string Format(string format, object arg,

                            IFormatProvider formatProvider)

    {

        // format doubles to 3 decimal places

        return string.Format(enUsCulture, "{0:0.000}", arg);

    }

 

    public object GetFormat(Type formatType)

    {

        return (formatType == typeof(ICustomFormatter))

            ? this : null;

    }

}



Having this formatter, we can use it like this:

double width = 15.77555;

double height = 12.8497979;

Console.WriteLine(

    string.Format(new DoubleFormatter(), "w={0} h={1}", width, height));



Output:

w=15.776 h=12.850



So now we have a reusable format for doubles - 3 decimal places with dot separator. That is nice, but this formatter is very simple - it formats everything (eg. DateTime) as "0:000". This is a fast version if you know that you will only use it for formatting lots of doubles.

The real version should look like this:

public class DoubleFormatter : IFormatProvider, ICustomFormatter

{

    // always use dot separator for doubles

    private CultureInfo enUsCulture =

        CultureInfo.GetCultureInfo("en-US");

 

    public string Format(string format, object arg,

                        IFormatProvider formatProvider)

    {

        if (arg is double)

        {

            if (string.IsNullOrEmpty(format))

            {

                // by default, format doubles to 3 decimal places

                return string.Format(enUsCulture, "{0:0.000}", arg);

            }

            else

            {

                // if user supplied own format use it

                return ((double)arg).ToString(format, enUsCulture);

            }

        }

        // format everything else normally

        if (arg is IFormattable)

            return ((IFormattable)arg).ToString(format, formatProvider);

        else return arg.ToString();

    }

 

    public object GetFormat(Type formatType)

    {

        return (formatType == typeof(ICustomFormatter)) ? this : null;

    }

}



Example:

Console.WriteLine(string.Format(new DoubleFormatter(),

    "Numbers {0} and {1:0.0}." +

    "Now a string {2}, a number {3}, date {4} and object: {5}",

    1.234567, -0.57123456, "Hi!", 5, DateTime.Now, new object()));



Output:

Numbers 1.235 and -0.6. Now a string Hi!, a number 5, date 12.6.2009 17:11:35 and object: System.Object



This article should give you an overview of implementing custom IFormatProvider. Now you should be able to modify the code to suit your specific needs.

Other examples with custom formatters can be found in MSDN. See example with formatter for 12-digit account numbers (12345–678–9012).

Posted by Martin Konicek on 2:02 PM

2 comments:

Anonymous said...

Thanks!

Post a Comment