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

Osk*_*lin 28 .net c# globalization object

将例如a转换为decimala时string,使用CultureInfo.InvariantCulture并将其作为传递给IFormatProvider.但为什么这种超载不在object

一个很好的实现是:

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

public virtual string ToString(IFormatProvider provider)
{
   return ToString();
}
Run Code Online (Sandbox Code Playgroud)

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

让我遇到这个的问题是当我创建一个方法来获取类的所有属性并将其写入xml时.因为我不想检查对象的类型,我只是打电话ToString.但这是一个小数,输出将基于CurrentCulture线程,这不是最佳的.我能看到的唯一解决方法是更改CurrentCultureto 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());
            }
        }
Run Code Online (Sandbox Code Playgroud)

但我希望它是:

        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));
            }
        }
Run Code Online (Sandbox Code Playgroud)

没有这种过载的任何好处object

Pet*_*ter 29

试着投你valueIFormattable:

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));
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @dlev:我不同意 - OP特别希望*只是*来格式化.鉴于类型可以轻松实现IFormattable而不是IConvertible,并且IFormattable中的单个方法正是OP想要调用的方法,我认为IFormattable更有意义. (5认同)
  • "IConvertible"实际上更有意义(除非你打算格式化数字.) (3认同)

sid*_*don 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();
}
Run Code Online (Sandbox Code Playgroud)


Nei*_*eil 8

尝试以下方法之一:

string valueString = XmlConvert.ToString(value);
string valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
Run Code Online (Sandbox Code Playgroud)

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

XmlConvert.ToString(DateTime.UtcNow)
Run Code Online (Sandbox Code Playgroud)

但这有效:

XmlConvert.ToString(DateTime.UtcNow, "o")
Run Code Online (Sandbox Code Playgroud)

  • Convert.ToString实际上转换为IConvertible和IFormattable(参见前面的帖子):public static string ToString(Object value,IFormatProvider provider){IConvertible ic = value as IConvertible; if(ic!= null)返回ic.ToString(provider); IFormattable formattable =值为IFormattable; if(formattable!= null)返回formattable.ToString(null,provider); 返回值== null?String.Empty:value.ToString(); } (3认同)