你似乎误解了.NET Framework的格式化基础架构设计。在实现时,永远不应该引用,因为这会与该接口的预期目的发生冲突。
只有当对象知道如何格式化自己时,它才应该实现(理想情况下,它应该将其委托给另一个类,但这里存在故意的耦合)。一个对象可能知道如何以多种不同的方式格式化自己,因此格式字符串允许您在它们之间进行选择。即使是这样,仍然可能缺少信息,如各种文化差异。因此,第二个参数提供了间接的信息。
传递给的类型旨在成为特定于提供的类的类型或接口。
例如,内置的数字类型希望能够检索的实例,而与< DateTime >相关的类希望能够检索。
实现
让我们想象一下,我们正在创建一些新的自我格式化类。如果它只知道一种格式化方法,那么它应该简单地重写object.ToString()
,仅此而已。如果这个类知道多种格式化方法,那么它应该实现IFormattable
接口。
format
参数
根据IFormattable.ToString
的文档,"G"
(表示通用格式)的格式字符串必须被支持。建议将null或空格式字符串视为等同于"G"
格式字符串。否则确切的含义由我们决定。
formatProvider
参数
如果我们需要任何与文化相关的东西,或者其他可能会变化的信息,我们需要利用IFormatProvider
参数。我们会使用IFormatProvider.GetFormat
从中请求某些类型。如果IFormatProvider
为空,或者如果IFormatProvider.GetFormat
对于我们想要的类型返回null,我们应该回退到某个默认来源以获取这些变化的信息。
默认的源不一定是静态的。可以想象,默认源可能是应用程序中的用户设置,而formatProvider
用于预览选项更改和/或在需要序列化的固定格式时使用。
还有可能需要格式化某些子对象。在这种情况下,您可能希望向下传递IFormatProvider
。MSDN有一个优秀的示例,展示了实现IFormattable
的这种情况。
其他ToString
重载
在实现IFormattable
时,重要的是以以下等效方式覆盖Object.ToString()
public override string ToString()
{
return this.ToString(null, System.Globalization.CultureInfo.CurrentCulture);
}
这样做可以确保
somestring + yourobject
等同于
string.Format("{0}{1}",somestring, yourobject)
,这是您的用户期望的结果。
为了方便用户,您可能需要提供
string ToString(string format)
。此外,如果您的默认格式有任何可从
IFormatProvider
中受益的变化组件,则还可以提供
public string ToString(IFormatProvider provider)
。
ICustomFormatter
那么,如果我们想要格式化一个不知道如何自我格式化的类,或者我们想要使用一些类本身不支持的格式,该怎么办呢?这就是
ICustomFormatter
发挥作用的地方。可以将能够提供
ICustomFormatter
类型的
IFormatProvider
作为参数传递给
string.Format
和
StringBuilder.AppendFormat
等方法。
提供的
ICustomFormatter
会在每次调用
string.Format
时调用其
Format
方法。如果
ICustomFormatter
对使用的格式字符串不熟悉或不支持该类型,则简单地委托给
IFormattable.ToString
或
Object.ToString
。
ICustomFormatter
文档提供了一个列表,如果您要格式化尚未提供格式支持的对象,需要做什么,以及如果您仅想为现有的
IFormattable
添加额外格式,需要做什么。它还提供了一个添加额外格式的示例。
参考
此MSDN页面提供了.NET格式化系统的很好的概述,并提供了与MSDN中几乎所有其他相关页面的链接。对于几乎任何格式化相关问题,这都是最好的起点。
ICustomFormatter
与IFormatProvider
一起使用的唯一原因是它是1.0框架的后期添加,他们不想添加一个新的string.Format
重载。 - Kevin Cathcart