为什么对象没有接受IFormatProvider的重载?
将例如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
过载的任何好处?
尝试将您的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解决方案的便捷扩展方法(经过修改以测试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更接近XML规范,例如使用“true”而不是“True”。 但是,它也比Convert.ToString()更脆弱。 例如,由于UTC时间,这将抛出exception:
XmlConvert.ToString(DateTime.UtcNow)
但这有效:
XmlConvert.ToString(DateTime.UtcNow, "o")