24

IFormatProviderDateTime オブジェクトのカスタム フォーマット文字列を認識する実装を作成しようとしていました。これが私の実装です:

 public class MyDateFormatProvider : IFormatProvider, ICustomFormatter
 {
  public object GetFormat(Type formatType)
  {
   if (formatType == typeof(ICustomFormatter))
   {
    return this;
   }
   return null;
  }

  public string Format(string format, object arg, IFormatProvider formatProvider)
  {
   if(arg == null) throw new ArgumentNullException("arg");
   if (arg.GetType() != typeof(DateTime)) return arg.ToString();
   DateTime date = (DateTime)arg;
   switch(format)
   {
    case "mycustomformat":
     switch(CultureInfo.CurrentCulture.Name)
     {
      case "en-GB":
       return date.ToString("ddd dd MMM");
      default:
       return date.ToString("ddd MMM dd");
     }
    default:
     throw new FormatException();
   }
  } 

私はそのようにメソッドでそれを使用できると思っていましたDateTime.ToString(string format, IFormatProvider provider)が、:

DateTime d = new DateTime(2000, 1, 2);
string s = d.ToString("mycustomformat", new MyDateFormatProvider());

この例では、US Culture で実行すると、結果は"00cu0Ao00or0aA"になります。これは、標準の DateTime 形式の文字列が解釈されているためと思われます。

ただし、次の方法で同じクラスを使用すると:

DateTime d = new DateTime(2000, 1, 2);
string s = String.Format(new MyDateFormatProvider(), "{0:mycustomformat}", d);

つまり、期待どおりの結果が得られます"Sun Jan 02"

結果の違いがわかりません。誰か説明してくれませんか?

ありがとう!

4

3 に答える 3

22

簡単な説明は、

DateTime.ToString(string format, IFormatProvider provider)

パラメータの1つとして実装するものを渡すことができますがIFormatProvider、実際にはIFormatProviderコード内で実装できる2つのタイプのみをサポートしています:

DateTimeFormatInfoまたCultureInfo

パラメータを ( を使用してas) またはそれらのいずれかにキャストできない場合、メソッドはデフォルトで になりますCurrentCulture

String.Formatは、そのような制限によって制限されません。

于 2010-03-04T20:26:40.320 に答える
11

DateTime.ToStringReflector でメソッドを確認すると、DateTime構造がDateTimeFormatInfo.GetInstanceメソッドを使用して、フォーマットに使用されるプロバイダーを取得していることがわかります。は、渡されたプロバイダからDateTimeFormatInfo.GetInstanceのタイプのフォーマッタを要求します。あなたの例が示すように、メソッドはメソッドのようにインターフェースを尊重していないようです。DateTimeFormatInfoICustomFormmaterDateTimeFormatInfoCultureInfoDateTime.ToStringICustomFormatterStringBuilder.FormatString.Format

DateTime.ToStringメソッドがインターフェイスをサポートする必要があることに同意しますが、現在はサポートICustomFormatterされていないようです。これはすべて変更されているか、.NET 4.0 で変更される予定です。

于 2010-03-04T20:07:03.283 に答える
3

拡張メソッドを使用してください:)

public static class FormatProviderExtension
    {
        public static string FormatIt(string format, object arg, IFormatProvider formatProvider)
        {
            if (arg == null) throw new ArgumentNullException("arg");
            if (arg.GetType() != typeof(DateTime)) return arg.ToString();
            DateTime date = (DateTime)arg;
            switch (format)
            {
                case "mycustomformat":
                    switch (CultureInfo.CurrentCulture.Name)
                    {
                        case "en-GB":
                            return date.ToString("ddd dd MMM");
                        default:
                            return date.ToString("ddd MMM dd");
                    }
                default:
                    throw new FormatException();
            }
        }

        public static string ToString(this DateTime d, IFormatProvider formatProvider, string format)
        {
            return FormatIt(format, d, formatProvider);
        }
    }
于 2010-03-04T20:14:49.880 に答える