2009-11-08 32 views

回答

32
  • IFormattable是支持格式string.Format一个目的,即在{0:xxx}xxx。如果对象支持该接口,则string.Format将委托给对象的IFormattable.ToString方法。

  • IFormatProvider是格式化程序用于文件特定日期和货币布局等配置信息的来源。

  • 但是,对于例如DateTime,其中您要格式化的实例已实现IFormattable,但您不控制实现(在BCL中提供DateTime,您无法轻易替换它),但有一种机制可以防止string.Format从简单地使用IFormattable.ToString。相反,你实现了IFormatProvider,并且当询问ICustomFormatter实现时,返回一个。 string.Format在委托给对象的IFormattable.Format之前检查提供商的ICustomFormatter,这反过来可能会要求IFormatProvider获取特定于文化的数据,如CultureInfo

这里有一个程序,它显示了string.Format询问IFormatProvider的,并且控制流程如何去:

using System; 
using System.Globalization; 

class MyCustomObject : IFormattable 
{ 
    public string ToString(string format, IFormatProvider provider) 
    { 
     Console.WriteLine("ToString(\"{0}\", provider) called", format); 
     return "arbitrary value"; 
    } 
} 

class MyFormatProvider : IFormatProvider 
{ 
    public object GetFormat(Type formatType) 
    { 
     Console.WriteLine("Asked for {0}", formatType); 
     return CultureInfo.CurrentCulture.GetFormat(formatType); 
    } 
} 

class App 
{ 
    static void Main() 
    { 
     Console.WriteLine(
      string.Format(new MyFormatProvider(), "{0:foobar}", 
       new MyCustomObject())); 
    } 
} 

它打印此:

Asked for System.ICustomFormatter 
ToString("foobar", provider) called 
arbitrary value 

如果格式提供改为返回自定义格式化程序,它接管:

class MyFormatProvider : IFormatProvider 
{ 
    public object GetFormat(Type formatType) 
    { 
     Console.WriteLine("Asked for {0}", formatType); 
     if (formatType == typeof(ICustomFormatter)) 
      return new MyCustomFormatter(); 
     return CultureInfo.CurrentCulture.GetFormat(formatType); 
    } 
} 

class MyCustomFormatter : ICustomFormatter 
{ 
    public string Format(string format, object arg, IFormatProvider provider) 
    { 
     return string.Format("(format was \"{0}\")", format); 
    } 
} 

当运行:

Asked for System.ICustomFormatter 
(format was "foobar") 
+0

为什么你在'MyFormatProvider.GetFormat'中返回'CultureInfo.CurrentCulture.GetFormat'?你会在'MyCustomFormatter.Format'中使用'IFormatProvider'吗? – Svish 2009-11-09 10:02:34

+0

默认格式提供程序是CultureInfo.CurrentCulture;如果你没有在'string.Format'的重载中指定一个,那么就使用它。我已经解释了IFormatProvider的用途 - 为日期格式设置提供配置信息(例如,询问CultureInfo)(例如使用CultureInfo.DateTimeFormat)。 – 2009-11-09 11:33:17

1

IFormattable是支持不同(命名/自定义)格式(例如数字等)的对象。通过使用接口,多个代码块可以使用值和格式字符串,这是很常见的(例如)在数据绑定和string.Format

一个IFormatProvider填补了一些处理格式的空白 - 特别是国际化。通常使用CultureInfo作为提供者,既可以提供特定的本地格式,也可以使用不变文化。

据我所知,ICustomFormatter是不相关的,并且更系列化(BinaryFormatter)。我可能是错误...

一个IFormattable对象的示例:

IFormattable d = 123.45M; 
string s1 = d.ToString("c", CultureInfo.CurrentCulture), // local currency 
     s2 = d.ToString("c", CultureInfo.InvariantCulture); // invariant currency 
+2

这是一个非常古老的答案,但为了孩子着想:'ICustomFormatter'确实约字符串格式化,并且不属于'增加对格式字符串的支持类型IFormattable'实现(或者为'IFormattable'对象提供不同的格式字符串)。 IFormatter是关于序列化的一个。 – 2014-01-30 21:18:09

相关问题