2011-09-22 17 views
27

たとえば、decimalstringに変換する場合はCultureInfo.InvariantCultureを使用し、IFormatProviderとして渡します。しかし、なぜこの過負荷はobjectにありませんか?オブジェクトにIFormatProviderを受け入れるオーバーロードがないのはなぜですか?

素敵な実装は次のようになります。

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

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

これはobjectクラスに害や利益を生じないだろうが、そこから派生するオブジェクトではなく、過負荷を上書きすることができ、ときにそれを呼び出すことは非常に簡単になりますあなたはそのタイプが不明です。

私がこの問題に遭遇したのは、クラスのすべてのプロパティを取得してxmlに書き込むメソッドを作成したときでした。オブジェクトのタイプを確認したくないので、私はちょうどToStringを呼び出しました。しかし、これは小数であったでしょうか?出力は最適ではないスレッドのCurrentCultureに基づいています。私が見ることができる唯一の回避策は、InvariantCultureCurrentCultureを変更して、元の状態に戻すことです。

 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()); 
      } 
     } 

しかし、私はそれになりたいでしょう:しかし、私は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(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の1つのメソッドがOPが呼びたいものと同じであることを考えれば、IFormattableは理にかなっています。 –

+0

@Jon OPの質問によれば、実際には 'Toon()'の 'IConvertible'バージョンを使っている経験があるようです。あなたのポイントは、しかし、撮影されています。 – 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(オブジェクト値、IFormatProviderプロバイダ){ IConvertible IC = value as IConvertible; if(ic!= null) 戻り値ic.ToString(プロバイダー)。 IFormattable = IFormattableとしてのformattable; if(formattable!= null) return formattable.ToString(null、provider); 戻り値== null? String.Empty:value.ToString(); } –