为什么对象没有接受IFormatProvider的重载?

时间:2011-09-22 20:46:59

标签: c# .net object globalization

decimal转换为string时,您使用CultureInfo.InvariantCulture并将其作为IFormatProvider传递。但为什么这个超载不在object

一个很好的实现是:

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

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

这对object类没有任何伤害或好处,但是从它派生的对象可以覆盖重载,当你不确定类型时调用它会容易得多。

让我遇到这个的问题是当我创建一个方法来获取类的所有属性并将其写入xml时。由于我不想检查对象的类型,我只是调用了ToString。但这是一个小数,输出将基于线程的CurrentCulture,这不是最佳的。我能看到的唯一解决方法是将CurrentCulture更改为InvariantCulture,然后将其更改回之前的状态。但那只会是丑陋的,因为我必须先写下试试块等等。

我目前的代码是:

        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());
            }
        }

但我希望它是:

        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));
            }
        }

object没有过载的任何好处?

3 个答案:

答案 0 :(得分:29)

尝试将value转换为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));
    }
}

答案 1 :(得分:14)

Peter解决方案的便捷扩展方法(经过修改以测试IConvertible)。

public static string ToInvariantString(this object obj)
{
    return obj is IConvertible ? ((IConvertible)obj).ToString(CultureInfo.InvariantCulture)
        : obj is IFormattable ? ((IFormattable)obj).ToString(null, CultureInfo.InvariantCulture)
        : obj.ToString();
}

答案 2 :(得分:8)

尝试以下方法之一:

string valueString = XmlConvert.ToString(value);
string valueString = Convert.ToString(value, CultureInfo.InvariantCulture);

XmlConvert.ToString()是针对XML而制作的,因此它会更接近XML规范,例如使用“true”而不是“True”。但是,它也比Convert.ToString()更脆弱。例如,由于UTC时间,这将引发异常:

XmlConvert.ToString(DateTime.UtcNow)

但这有效:

XmlConvert.ToString(DateTime.UtcNow, "o")