Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么';对象是否有接受IFormatProvider的重载?_C#_.net_Object_Globalization - Fatal编程技术网

C# 为什么';对象是否有接受IFormatProvider的重载?

C# 为什么';对象是否有接受IFormatProvider的重载?,c#,.net,object,globalization,C#,.net,Object,Globalization,例如,将十进制转换为字符串时,使用CultureInfo.InvariantCulture并将其作为IFormatProvider传递。但是为什么这个重载不在对象中呢 一个很好的实现是: public virtual string ToString() { // yadayada, usual ToString } public virtual string ToString(IFormatProvider provider) { return ToString(); } 这不会

例如,将
十进制
转换为
字符串
时,使用
CultureInfo.InvariantCulture
并将其作为
IFormatProvider
传递。但是为什么这个重载不在
对象中呢

一个很好的实现是:

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

public virtual string ToString(IFormatProvider provider)
{
   return ToString();
}
这不会对
对象
类造成任何伤害或好处,但是从它派生的对象可以替代重载,并且当您不确定类型时,调用重载会容易得多

让我遇到这种情况的问题是,当我创建一个方法时,该方法将获取类的所有属性并将其写入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));
            }
        }

对象上没有此重载有什么好处?

尝试将
值转换为
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)

请尝试以下方法之一:

string valueString = XmlConvert.ToString(value);
string valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
ToString()是为XML设计的,因此它将使内容更接近XML规范,例如使用“true”而不是“true”。但是,它也比Convert.ToString()更脆弱。例如,由于UTC时间,这将引发异常:

XmlConvert.ToString(DateTime.UtcNow)
但这是可行的:

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

IConvertible
实际上更有意义(除非你打算格式化数字)。@dlev:我不同意——OP特别想格式化数字。考虑到类型可能很容易实现IFormattable,但不是IFormattable,而且IFormattable中的单个方法正是OP想要调用的方法,我认为IFormattable更有意义。@Jon根据OP的问题,看起来他有实际使用
ToString()
版本的
IConvertible
的经验,这就是我提到它的原因。您的观点很好理解,不过.Convert.ToString实际上强制转换为IConvertible和IFormattable(请参阅前面的文章):公共静态字符串ToString(对象值,IFormatProvider提供程序){IConvertible ic=value as IConvertible;if(ic!=null)返回ic.ToString(提供程序);IFormattable formattable=作为ifformattable的值;if(formattable!=null)返回formattable.ToString(null,提供程序);返回值==null?String.Empty:value.ToString();}
XmlConvert.ToString(DateTime.UtcNow, "o")