您似乎误解了.NET Framework格式化基础架构的设计。 ICustomFormatter
不应在IFormattable.ToString
的实现中引用,因为它与该接口的预期用途相冲突。
IFormattable
的对象应该只实现IFormattable
如果它知道如何格式化本身(理想情况下,应该委派到另一个类的课程,但这里会有故意耦合)。一个对象可能知道如何以多种不同的方式进行格式化,所以格式字符串允许你在它们之间进行选择。即使如此,仍然可能会丢失信息,这些信息因文化而异。因此,有第二个参数间接提供这些信息。
传递给IFormatProvider.GetFormat
的类型是打算成为IFormatProvider
提供给该类的特定类型或接口。
例如,内置的数字类型希望能够检索System.Globalization.NumberFormatInfo
的实例,而DateTime
相关的类希望能够检索System.Globalization.DateTimeFormatInfo
。
实施IFormattable
让我们想象一下,我们正在创造一些新的自我格式化类。如果它只知道一种格式化的方法,它应该简单地覆盖object.ToString()
,仅此而已。如果班级知道不止一种格式化方式应该执行IFormattable
。
的format
参数
每IFormattable.ToString
the documentation的"G"
格式字符串(其表示的一般格式)必须得到支持。建议将null或空格式的字符串与"G"
的格式字符串等效。确切的意义在其他方面取决于我们。
的formatProvider
参数
如果我们需要什么特定的文化,或否则将发生变化,我们需要利用IFormatProvider
参数。我们会使用IFormatProvider.GetFormat
来请求某种类型。如果IFormatProvider
为空,或者IFormatProvider.GetFormat
对于我们想要的类型返回null,我们应该回退到某些默认源以获取此不同信息。
默认来源不需要是静态的。可以想象,默认来源可能是应用程序中的用户设置,并且formatProvider
用于预览选项更改和/或当序列化需要固定格式时。
也有可能格式化可能涉及格式化一些子对象。在这种情况下,您可能想要通过IFormatProvider
。 MSDN有一个excellent example实施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
的方法中作为IFormatProvider
参数传递。
提供的ICustomFormatter
对string.Format
所做的每种格式都要求其Format
方法。如果ICustomFormatter
不熟悉所使用的格式字符串或不支持该类型,那么它只是代表IFormattable.ToString
或Object.ToString
。如果您格式化尚未提供格式支持的对象,则ICustomFormatter
documentation提供了所需内容的列表,如果您只想向现有的IFormattable
添加额外格式,则需要什么。它还提供了添加额外格式大小写的例子。
参考
This MSDN page提供了.NET格式化系统的一个很好的概述,并提供链接到MSDN几乎所有的其他相关网页。这是几乎所有与格式相关的问题开始的最佳位置。
感谢您的详细解答和参考! –
当我第一次看到这个问题时,我基本上和以前一样对所有这些都感到困惑,所以我看着反射器的框架,开始阅读MSDN页面,而我只是更加困惑。在我找到主要参考页面之前,我已经阅读了大部分MSDN页面。即使如此,它开始点击之前花了一段时间。有一些棘手的部分。例如,我怀疑'ICustomFormatter'与IFormatProvider一起使用的唯一原因是因为它是1.0框架的一个晚期附加,并且他们不想添加新的'string.Format'重载。 –