Search code examples
c#.netobjectglobalization

Why doesn't object have an overload that accepts IFormatProvider?


When converting for instance a decimal to a string, you use the CultureInfo.InvariantCulture and pass it as an IFormatProvider. But why is this overload not in object?

A nice implementation would be:

public virtual string ToString()
{
   // yadayada, usual ToString
}

public virtual string ToString(IFormatProvider provider)
{
   return ToString();
}

This would cause no harm or benefit to the object class, but objects deriving from it can instead override the overload and it will be a lot easier to call it when you are unsure of the type.

The problem that made me run into this was when I was making a method that would be getting all properties of a class and writing it to xml. As I didn't want to check the type of the object, I just called ToString. But would this have been a decimal, the output would be based on the CurrentCulture of the thread, which is not optimal. The only workaround I can see is changing the CurrentCulture to InvariantCulture and then changing it back to whatever it was before. But that would just be ugly as I would have to write try finally blocks etc.

My current code is:

        foreach (var property in typeof(Order).GetProperties(BindingFlags.Public | BindingFlags.Instance).
            Where(c => ValidTypes.Contains(c.PropertyType)))
        {
            var value = property.GetValue(order, null);
            if (value != null)
            {
                writer.WriteElementString(property.Name, 
                value.ToString());
            }
        }

But I would want it to be:

        foreach (var property in typeof(Order).GetProperties(BindingFlags.Public | BindingFlags.Instance).
            Where(c => ValidTypes.Contains(c.PropertyType)))
        {
            var value = property.GetValue(order, null);
            if (value != null)
            {
                writer.WriteElementString(property.Name, 
                value.ToString(CultureInfo.InvariantCulture));
            }
        }

Any benefit of not having this overload on object?


Solution

  • Try to cast your value to IFormattable:

    foreach (var property in typeof(Order).GetProperties(BindingFlags.Public | BindingFlags.Instance).
           Where(c => ValidTypes.Contains(c.PropertyType)))
    {
        var value = property.GetValue(order, null);
        if (value != null)
        {
            var formattable = value as IFormattable;
            writer.WriteElementString(property.Name, 
            formattable == null ? value.ToString() : formattable.ToString(null, CultureInfo.InvariantCulture));
        }
    }