为什么对象没有接受 IFormatProvider 的重载?
例如,将十进制
转换为字符串
时,您可以使用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
上不重载有什么好处?
When converting for instance a decimal
to a string
, you use the CultureInfo.InvariantCulture
and pass it as an IFormatProvider
. But why is this overload not in object
?
A nice implementation would be:
public virtual string ToString()
{
// yadayada, usual ToString
}
public virtual string ToString(IFormatProvider provider)
{
return ToString();
}
This would cause no harm or benefit to the object
class, but objects deriving from it can instead override the overload and it will be a lot easier to call it when you are unsure of the type.
The problem that made me run into this was when I was making a method that would be getting all properties of a class and writing it to xml. As I didn't want to check the type of the object, I just called ToString
. But would this have been a decimal, the output would be based on the CurrentCulture
of the thread, which is not optimal. The only workaround I can see is changing the CurrentCulture
to InvariantCulture
and then changing it back to whatever it was before. But that would just be ugly as I would have to write try finally blocks etc.
My current code is:
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());
}
}
But I would want it to be:
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));
}
}
Any benefit of not having this overload on object
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
尝试将您的
value
转换为IFormattable
:Try to cast your
value
toIFormattable
:Peter 解决方案的便捷扩展方法(经过修改以测试 IConvertible)。
Handy extension method of Peter's solution (modified to test also for IConvertible).
请尝试以下方法之一:
XmlConvert.ToString() 是为 XML 设计的,因此它会使事情更接近 XML 规范,例如使用“true”而不是“True”。然而,它也比 Convert.ToString() 更脆弱。例如,由于 UTC 时间,这将引发异常:
但这有效:
Try one of these:
XmlConvert.ToString() is made for XML, so it will keep things closer to the XML spec, such as using "true" instead of "True". However, it is also more brittle than Convert.ToString(). For example, this will throw an exception because of the UTC time:
but this works: