2011-09-22 31 views
27

将例如decimal转换为string时,可以使用CultureInfo.InvariantCulture并将其作为IFormatProvider传递。但为什么这个过载不在object为什么对象没有接受IFormatProvider的重载?

一个很好的实现是:

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

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

这会造成任何损害或受益于object类,但是从它派生对象可以代替重载过载,这将是一个更容易的时候调用它你不确定这种类型。

使我碰到这个问题是当我正在做一个方法,将获得一个类的所有属性,并将其写入XML。由于我不想检查对象的类型,我只是打电话给ToString。但是,这是十进制的,输出将基于线程的CurrentCulture,这不是最优的。我能看到的唯一解决方法是将CurrentCulture更改为InvariantCulture,然后将其更改回以前的状态。但是,这也只是丑,我会写尝试finally块等

我当前的代码是:

 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

回答

28

尝试投你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)); 
    } 
} 
+3

'IConvertible'其实更有意义 – dlev

+5

@ dlev:我不同意 - OP特别希望*只是*格式化。鉴于类型可以很容易地实现IFormattable但不是IConvertible,并且IFormattable中的单一方法恰好是OP想要调用的方法,我认为IFormattable更有意义。 –

+0

@Jon基于OP的问题,看起来他有实际使用'IConvertible'版本的'ToString()'的经验,这就是我提到它的原因。虽然你的观点很好。 – dlev

14

彼得的解决方案(修改也来测试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(); 
} 
8

尝试其中之一:

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

XmlConvert.ToString()是XML做,所以它将使事情变得更接近XML规范,如使用“真”,而不是“真”。但是,它也比Convert.ToString()更脆弱。例如,这将引发异常,因为UTC时间:

XmlConvert.ToString(DateTime.UtcNow) 

但这个工程:(除非你打算格式化数字)

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

Convert.ToString实际转换为IConvertible和IFormattable(请参阅以前的帖子): public static string ToString(Object value,IFormatProvider provider){ IConvertible ic = value as IConvertible; (ic! if(ic!= null) return ic.ToString(provider); IFormattable formattable = value as IFormattable;如果(formattable!= null) return formattable.ToString(null,provider); 返回值== null? String.Empty:value.ToString(); } –

相关问题