为什么对象没有一个接受IFormatProvider的重载?
本文关键字:IFormatProvider 重载 对象 有一个 为什么 | 更新日期: 2023-09-27 18:09:36
例如,当将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
,然后将其更改回之前的任何内容。但是那样会很难看,因为我必须写try 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
上没有这个重载有什么好处吗?
尝试将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));
}
}
Peter's solution的便捷扩展方法(修改后也可以测试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();
}
试试这些:
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")