Archive for the ‘.NET’ category

Expert F# Sample Chapter (Essential F#) from Don

October 23, 2006

Don Syme has posted chapter 2 from his upcoming Expert F# book. I have mirrored it here. Thanks, Don.

Advertisements

Interesting article on C# 3.0.

October 19, 2006

Concepts behind the C# 3.0 language

IFormatProvider and NumberFormatInfo nightmare

September 15, 2006

I was implementing FormatProvider to support a special unit of measure called basis points (bp) which basically means 1/10000.

class MyFormatInfo: IFormatProvider, ICustomFormatter
{
   #region IFormatProvider Members
   public object GetFormat(
Type formatType)
   {
      return this;
   }
   #endregion

   #region ICustomFormatter Members
   public string Format(string format, object arg,
IFormatProvider formatProvider)
   {
      string aLowerFormat = format.ToLowerInvariant();
      switch (aLowerFormat)
      {
         case
“bp”:
            return FormatNumeric(arg.ToString(), 10000);
         case
“pc”:
            return FormatNumeric(arg.ToString(), 100);
      }
      return string.Format(
CultureInfo.CurrentCulture, format, arg);
   }
 

   private static string FormatNumeric(string theNumber, decimal theMultiplier)
   {
      decimal aNumericValue;
      if (decimal.TryParse(theNumber, out aNumericValue))
      {
         aNumericValue *= theMultiplier;
         return aNumericValue.ToString(
“N”, CultureInfo.CurrentCulture);
      }
      else

      {
         return string.Empty;
      }
   } 
   #endregion

}

This works great when used with string.Format such as string.Format(“{0:bp}”, 0.01).

However, once it is being used with .ToString(new MyFormatProvider()), nothing works. It didn’t even hit the Format() method. The ToString(IFormatProvider) method supposedly works with custom format provider. (Unless why would it even accept IFormatProvider)

You might say, “Then just use the damn string.Format method.” I know, I know, but how would you bind your object to a datagrid and have the decimal or double value be displayed in the custom format?

grid.CellStyle.FormatProvider = new MyFormatProvider();
grid.CellStyle.Format = “bp”;

A trip to Reflector reveals the ugly implementation of decimal.ToString(IFormatProvider) and double.ToString(IFormatProvider). The truth is, they will check if the IFormatProvider is actually a NumberFormatInfo. If it’s not, then it will ignore everything and use the NumberFormatInfo from the CurrentCulture.

I don’t really understand why it was implemented that way, but okay Microsoft, how about I subclass from NumberFormatInfo. Then my format provider will be NumberFormatInfo, right? Right, except for one small detail: NumberFormatInfo is a sealed class. Bang…I hit my head against the wall again.

Then, my last resort is try to find standard format hack and lucky me, I found out that the format ‘%’ is doing no more than multiply the original number with 100 just like how the ‘,’ format is dividing by 100. So, here goes it.

NumberFormatInfo aCustomFormat = (NumberFormatInfo)

CultureInfo.CurrentCulture.NumberFormat.Clone();

aCustomFormat.PercentSymbol = “”;

decimal x = 0.0125M;

Console.WriteLine(x.ToString(“0.##%\%”, aCustomFormat));    // 1.25%

Console.WriteLine(x.ToString(“0.##%%bp”, aCustomFormat));   // 125bp

I was lucky this time, but if my requirements cannot be met by tricking ‘%’ or ‘,’, then I will be in trouble. Hopefully somebody will fix the ToString(IFormatProvider) implementation in the future or explain why it should be implemented this way.